Tzk Posted November 14, 2019 Posted November 14, 2019 (edited) Ok, checked and confirmed everything is working. So here's my ISA option rom for the A7N8X. I use cmos registers 75h, 76h and 77h to store my custom settings. As all settings only got 16 values i use 4 bits of every register to store a single setting: 75h: F0h is Drive Strength, 0Fh is Slewrate 76h: F0h is Super Bypass, 0Fh is Data Scavenged Rate 77h: F0h is Auto Precharge Everything else is in the comments of the ISA option rom. If you got questions, as always, just ask I used FASM to write this, so load this into FASM, hit compile and you get the option rom (4096bytes) which you can just include in your bios via cbrom.exe bios.bin /isa option-rom-file.bin. Note that this won't do anything unless you implement the bios items to actually store data in cmos register 75h to 77h. A7N8X-ISA-option-rom-v4.ASM Next up i probably need to write down how i modified the bios itself... So first i needed new labels for the available selections of the new items. To get these, i created a new label group in _EN_CODE.bin. _EN_CODE.bin works like this: At the start of the file you got a lookup table for the different label groups which points at the label group header. Below is my _EN_CODE.bin where i marked the available groups in yellow. If you'd have a look at for example offset 049Ch, 14C4h and so on, you'd find the label group headers there. Note that the label pointers are stored in little endian, so least significant byte first. You can just add another group and the bios will recognize it. In this case you could add your label directly after F05B (offset 5BF0h). Just remember to count the label number and note it down. We'll need this later when we modify the bios item in system.bin. Now, let's jump to the last group to see how it looks like. The last group is F05B and thus we jump to offset 5BF0h: Note that the first byte is 0A which is the number of sublabels this group has. In this case we got 10 labels and thus the value stored here is 0Ah. These 10 sublabels are again pointer to the actual label text and (of course) again in little endian notation. So the first label is 705A which translates to offset 5A70h. If we have a look at this offset, we read "Super Bypass" which is the actual item label text the bios will display. Note that every label must be preceeded by 00h and if you need spaces, you must use 20h instead of 00h. That's why "Super Bypass" is followed by 2020h and then a single 00h right in front of the next label. If you add a pointer for a new sublabel, always make sure to point to the label start and not the 00h right in front of it. Now if you want to create a group of selectable items, make sure all items got the exact same length. So if one items got a longer name, you'll need to fill all other options with spaces (use 20h for this, not 00h!) until all options got the same total length. You only need to point to the first label on the sublabel lookup table, the bios will read the following selection labels automatically. It also doesn't matter where you store the group+pointers relative to your labels. As long as the offsets are correct, it'll work. Next up is the system.bin with the bios item strings as we need to make the bios use our newly added labels. On the PDF i linked we find this: The bytes we're interested in are marked in yellow. To the left there's the pointer to the label of the option itself, in the middle there's the pointer to the available/selectable options and to the right there's the number of selectable options available. What we need to do now is to insert the position of our group in _EN_CODE.bin (1st, 2nd, 3rd group etc) into the bios item string and the position of our label inside that group. So inserting 05 06 would read the 5th label from the 6th label group. This applies for the item itself and also the selections. We also need to tell the bios how many options are available, else it won't read all labels correctly. Note: I'm not sure if the bios started counting at zero or 1. Iirc the 2nd group gets 01 as pointer. So better doublecheck this with a known to be working option on the bios. If everything went smoothly, we now got an option in bios which has the correct name and selections available. If you want to test this fast, just add system.bin and _EN_CODE.bin to a bios file with cbrom and open it with modbin. If modbin displays the menu tree correctly, there's a good chance at the bios will work. No other modules are needed inside the bios for this first test. What now needs to be done is to tell the bios which Cmos register it should write to. This is done by changing the "E8h" index shown above. That's the cmos register the bios will write to. Make sure you don't choose a register which is already in use! I used r/w everything (windows tool) on the stock bios to see the content of all Cmos registers before choosing 75h to 77h on my mod. The masks mentioned next to it allows to for example only write the first or last 4bits of the register. So if you want to store two settings on a single register, choose masks 0Fh on the first and masks F0h on the 2nd bios item. The selections will write the register content in increasing order. So if your selection labels are named linke this: Auto Ten twenty hundred Then Auto will write a zero, ten will write a 1, twenty a 2 and hundred a 3 to the cmos register. I always chose Auto as first item, so i can just check if the register is 0 in my option rom. And if yes, i just skip the custom code. Edited November 14, 2019 by Tzk 1 Quote
I.nfraR.ed Posted November 14, 2019 Posted November 14, 2019 (edited) Great work! The asm code is the easiest part for me, since we have a "template" and once everything is in bios, I can write then write the ISA option rom code. I think that I've got how to add the new labels and options and then update the items in "_ITEM.BIN" in the main bios. Will try it when I get back home. You only need to add in _EN_CODE.BIN the starting addresses of the label heading and first option item, right? SuperBypass seems to be enabled by default on NF7, Data Scavenged Rate is also set to Fast. DS and SR are the same for all DIMMs, but DFI sets them differently for the different DIMMs. Will still need to try more combinations, but something like 4/7 and 6/7 works better than the default 3/10. PS: Your code compiles fine under linux. Edited November 14, 2019 by I.nfraR.ed 1 Quote
Tzk Posted November 14, 2019 Posted November 14, 2019 3 minutes ago, I.nfraR.ed said: You only need to add in _EN_CODE.BIN the starting addresses of the label heading and first option item, right? Correct. Just give me a few minutes, i'm on the way of writing everything down Quote
I.nfraR.ed Posted November 14, 2019 Posted November 14, 2019 (edited) Alright. Think I got everything that needs to be done, just don't have a way to test it at work. I've been very busy with tasks at work and too tired to grasp the concept easily. It took me a while Btw, it should be possible to optimize all these comparisons of the set value. It should be better to just read the setting, e.g. drivestrength, mask it and set it to the register, instead of doing a switch with 16 cases. PS: Perhaps it's a good idea to put all relevant information from the thread into a new document, so it doesn't get lost so easily. Edited November 14, 2019 by I.nfraR.ed Quote
Tzk Posted November 14, 2019 Posted November 14, 2019 Just edited the post above to include the addition of labels in _EN_CODE.bin... Yes, you could probably just somehow modify it to just change the data based on the input value instead of using this (huge) switch. It's the first time i've written assembler, so i'm more or less happy that it works. It was an even bigger mess before i added the macro... Quote
I.nfraR.ed Posted November 14, 2019 Posted November 14, 2019 (edited) Ok, so we are counting only heading label, e.g. "Super Bypass" and starting option label, e.g. "Auto". All the rest are managed automatically, thus 5x2 is 10 in total? And you've used the extra 00 bytes just for padding between different heading labels? Edited November 14, 2019 by I.nfraR.ed Quote
Tzk Posted November 14, 2019 Posted November 14, 2019 (edited) Correct. You only need to specify the heading label and the first selection on the lookup table of the label group. If you got 5 bios items you want to fully label, then you'll have 10 pointers on the label group: 5 pointers for the heading labels and 5 pointers for the selectable options. The bios will handle reading the other available selections via the # of selections on the bios item string in system.bin. And this is the reason why all selection labels must be of equal length. The two empty lines (offset 5A60 and 5BE0) are just for padding and to make it a bit easier to read. You could just leave them out. However that'd obviously change your label position and thus the pointers on the lookup table. If you need to padd the selectable options themselves then use 20 instead of 00. You only got 00 directly in front of the start of a label. Edited November 16, 2019 by Tzk Quote
I.nfraR.ed Posted November 14, 2019 Posted November 14, 2019 (edited) Thanks, got it, I think. Abit bioses have 5 free options at the same place. Checked one Gigabyte bios and it's the same there - same 5 options at the same menu. To optimise the asm code, you'd need to move "Auto" to the end of the list and use corresponding Disabled/Enabled or Normal/Fast so they match 0 and 1. For the DS and SR it would work with "Auto" as a first option, since we have the usable options starting from 1 to 15. Edited November 14, 2019 by I.nfraR.ed Quote
Tzk Posted November 14, 2019 Posted November 14, 2019 (edited) It basically doesn't matter which option is listed first. You can specify a default value for both "load optimised defaults" and in case the cmos was cleared. So Auto doesn't need to be 00h. I just did this for convenience and to have Auto listed as first (topmost) option on all items in bios. You could possibly simplify the code on the DS and SR settings by just reading the cmos value and applying it directly onto the data register. Maybe with a bit shift to fill all neccessary bits. So basically: read cmos use helper variable to store setting apply helper variable to data register (ebx) bitshift helper, apply again (repeat if neccessary) then apply data as before onto desired pci register This would, if done smart, fully eliminate the need for the huge compare+jump table. Except for the auto settings (which is still 00h and should be applied anyways). I'm not sure if it's worth to mess with the settings which got only few options anyways (auto precharge, DSR, SuperBypass). However the slewrate and DS settings would significantly reduce the filesize. Edited November 14, 2019 by Tzk Quote
I.nfraR.ed Posted November 14, 2019 Posted November 14, 2019 (edited) Yes, that is my point. Moving the Auto to last, so it goes Disabled, Enabled, Auto - 0, 1, 2. Then set default option to 02 and in asm code read register saved settings. Compare to 02 instead of 00 and if not equal, set the actual value to the pci register. You can then reuse the same macro for setting all options with direct value from CMOS and only care about the correct shift, mask and register you want to modify. Congrats once again for the achievement. I think this should be the best bios for the Asus board. And we have the correct PCR files for those who don't have the bios options. If we could find how to add new items then it would be perfect, but works this way, too. Mission accomplished, I would say. Now what is left is to tune for different CPUs, e.g. high FSB and performance versions, 2T bios as well. PS: I can buy a Gigabyte GA-7N400 for like 15 euro and wonder if I should try it. The bios has a lot of hidden options that can be unlocked, but would also need a vcore mod, since it is just +5%, +10%. Same 5 free slots for additional items in bios. Edited November 14, 2019 by I.nfraR.ed Quote
Tzk Posted November 14, 2019 Posted November 14, 2019 (edited) 1 hour ago, I.nfraR.ed said: If we could find how to add new items then it would be perfect, but works this way, too. Yep, that's the only thing missing to be able to fully customize the bios. I'd love to add a ton of items just like on the DFI bios... I even wondered what happens if i try to port some of the bios item blocks (those confusing code blocks + the item strings) from DFI to Asus... No clue if the Gigabyte is a decent board. I guess you'd have to mod a bios for it anyways as there are only a few modbios available. Edited November 14, 2019 by Tzk Quote
I.nfraR.ed Posted November 14, 2019 Posted November 14, 2019 (edited) Btw, I was thinking if it is possible to set Command Rate with the ISA ROM and add that as an option instead of the e.g. Auto Precharge (we have that in windows tools, even without messing with WCPREDIT). That would be more useful, but I'm not sure if it is too late for CR. Would eliminate the need for a separate 1T and 2T bioses. PS: As for the Gigabyte board - all nforce2 boards need mods to unlock the full potential, especially bios. It looks like an OK board, but will have to mod a bios, add missing capacitors, vcore, vdd and vdimm mods. Then it's just a matter of lucky chipset. Edited November 14, 2019 by I.nfraR.ed Quote
I.nfraR.ed Posted November 15, 2019 Posted November 15, 2019 (edited) Got the menus working yesterday. Will have to test if I can make Command Rate work. If not, will replace it with Auto Precharge. Using CMOS register 75 for Drive Strength and Slew Rate (4 bits each) and register 76 for the rest (2 bits each, so 2 more bits are free from this register). I was thinking that we could sacrifice some of the IDE Channel options that I never seem to touch and reuse these settings for alpha timings. The menus are setup to save the exact value I need for the option rom without using long switches and comparisons. I will only check for "auto". Also, I've verified everything starts from index 0 - the label groups, the label position in the group, the options, so e.g. 12th group would be 0Bh and not 0Ch. Edited November 15, 2019 by I.nfraR.ed 3 Quote
Tzk Posted November 16, 2019 Posted November 16, 2019 (edited) Very nice, congrats! Looks like my effort to document everything paid off already. I'm still investigating if it's possible to add new items. Luckily Asus increased the number of bios items when going releasing newer bios versions. 1006 got 212 items, 1007 213 and 1008 has 214 items. But (and that's the bad part): the system.bin changes are all over the place. It looks like the code interacts heavily with the items, the item offsets and the misterious codeblocks in front and directly after the item strings. It looks like even a single added items string shifts a lot of offsets in the code as the following strings and mysterious blocks are moved by 25bytes. There are also changes inside those blocks which is why i think those blocks aren't neccessarily code, but some kind of lookup table (just like the label groups in _EN_CODE.bin). However i'm currently not able to see any scheme on how this was done. It's either too complex to understand it while looking at hex files or the changes are done at several places simultaneously which will make it almost impossible to tweak the hex file by hand to get new items. If only we had the sources of those bios files... EDIT: What about the Head, Landing and Blocks items you see when you select the submenu for drives? Do we need these? That'd give us 10+ items to work with. Edited November 16, 2019 by Tzk Quote
Tzk Posted November 16, 2019 Posted November 16, 2019 (edited) And a thought regarding the Tref: Shouldn't the refresh time (in nanoseconds) stay the same when we use different dram clocks? I guess that Tref is set in clocks (not time), so when changing fsb it should also change. Various dram chip datasheets state that Tref must be ~7.8us ( =7800ns). So if we calculate how many clocks it takes to last 7.8us at a given frequency, then we should find Tref, no?! 200MHz = 5ns -> 7800ns / 5ns = 1560 clocks -> 618h 166Mhz = 6ns -> 7800ns / 6ns = 1300 clocks -> 514h 133Mhz = 7.5ns -> 7800ns / 7.5 = 1040 clocks -> 410h 100Mhz = 10ns -> 7800ns / 10ns = 780 clocks -> 30Ch I dumped all chipset registers with WCPRedit at different FSBs while i kept all other settings equal (multi, volts,....). I used the Asus stock 1008 bios with 3.02BPL. And i think i found something: B0D0F1 (the function which does also store the alpha timings) at offset 60h and 61h. I assumed little endian notation: 200Mhz: 1A06h -> 061Ah -> 1562 (clocks?!) 166Mhz: 1605h -> 0516h -> 1302 133Mhz: 1104h -> 0411h -> 1041 100Mhz: 0D03h -> 030Dh -> 781 Looks VERY similar to above, doesn't it?! So, i conclude that offsets 60 and 61 may be Tref I tried several values (100Mhz to 245Mhz in small steps) and plotted everything. Here's the result for my A7N8X. It's very interesting to see that Asus actually increases the time between refreshs at 100/133/166/200Mhz. These are visible as the four highest points on the grey curve. And it looks like Asus does more refreshs above 200mhz with the most refreshs occuring at ~225Mhz. Above that they're decreasing the refreshs again. The (JEDEC) standard value for ddr1 is 7800ns, while more refresh should increase stability but decrease bandwidth. / I noticed that some people use way higher values on S.939. On my Asus i got 1560 cycles at DDR400 while some users on DFI Ultra-D use 3000 to 4000 at DDR600. That'd translate to 2000-2600cycles at 200Mhz. So there might be performance left, depending on the exact chips we use. Here's the data for the diagram, i also calculated the absolute and relative delta between actual and calculated value per frequency. What matters most are the first three columns though. Edited November 17, 2019 by Tzk 2 2 Quote
I.nfraR.ed Posted November 19, 2019 Posted November 19, 2019 Can someone check what these read on Asus: PCI offset 1T 2T DFI ABIT DFI ABIT B0/D0/F1 87 03 03 23 23 99 21 31 32 42 9A 54 65 65 76 F9 44 45 45 46 DFI is controlled by bios option, Abit 1T is stock, while 2T is my old CPC-OFF modded bios. Quote
Tzk Posted November 19, 2019 Posted November 19, 2019 87: 03 99: 31 9A: 65 F9: 45 Used my modded bios on A7N8X DLX v2.0 with BPL3.19 1T taken from Taipan 0.3 bios. 1 Quote
I.nfraR.ed Posted November 19, 2019 Posted November 19, 2019 (edited) Unfortunately doesn't seem to be able to set Command Rate. Hardcoded the other 3 registers. With just Command rate, 1T works, because there's no change in the register. Basically setting the bit to 0 again. When set to 2T I get a blinking cursor after POST. Together with the hardcoded registers, both 1T and 2T don't work. Still can use Auto though, since it skips to the end. Getting a system lock if I try to set any of these offsets in windows. The relevant code: macro writePciReg pcireg, data, mask { mov ebx, data ; move data we want to set mov eax, pcireg ; move address for 32bit register offset mov dx, 0CF8h ; pci register address port out dx, eax ; set port we want to read mov dx, 0CFCh ; pci register data port in eax, dx ; read register values and eax, mask ; mask for data to remove pre-set value, usually the inverse of the data we set or eax, ebx ; add custom value to old register data out dx, eax ; write new custom register value } ; macro getCmosData cmosreg { mov eax, 0 ; reset eax mov al, cmosreg ; set CMOS index out 70h, al ; send register offset in al, 71h ; fetch data } ; ;==================================================================== ; SET COMMAND RATE getCmosData 76h; ; get CMOS register data and al, 3h; ; get lowest 2 bits cmp al, 2h ; skip if auto je codeend ; shl eax, 29 ; we need to set bit 5 in offset 87 ; writePciReg 80000184h, eax, 0DFFFFFFFh ; hardcoded for 2T writePciReg 80000198h, 000764200h, 0FF0000FFh writePciReg 800001F8h, 000004600h, 0FFFF00FFh jmp codeend However, I've found a post in XS that mentions 2 of these offsets for controlling CAS Quote NoOne said:10-05-2005 12:36 PM STEvil, i have some really good news To change from CAS 2.5 to CAS2.0 you must change this Offsets PCI Bus#0 Dev#0 Func#1 Offset# Offset 71 = 24 to 04 Offset 75 = 24 to 04 Offset 9A = 76 to 65 Offset A0 = 6A to 2A Offset A8 = 6A to 2A Offset B0 = 6A to 2A Offset F9 = 46 to 45 PS: Actually I can set F9, but not the others. Edited November 19, 2019 by I.nfraR.ed Quote
Tzk Posted November 19, 2019 Posted November 19, 2019 So setting CMD after POST is a nogo then. I finally decided to switch my bios settings from data scavenged rate, superbypass and autoprecharge to Trc, Trfc and Tref. i already got them working in bios, next is the option rom. So i got Data strength, slew rate, Trc, Trfc and Tref in bios. Still i haven't managed to add new settings and i fear it's just too complex to get it done on the compiled bios. So i'll try to recycle other bios options next. Have you tried to for example use the Cylinder, Head, Sector and Landing Zone (display) fields of the harddrives? I got 20 items in total for this... (5 items for 4 drives each). Quote
I.nfraR.ed Posted November 19, 2019 Posted November 19, 2019 (edited) Maybe I'm doing something wrong, but couldn't make it work. Even tried DFI BPL which is 2T by default - same outcome, just in the opposite direction. Maybe there is a sequence to set CR, like the one for CAS above. But perhaps it's just too late at that stage. I will compare saved CMOS registers for 1T and 2T BPL with everything else the same (full manual settings), but I guess DFI has an additional logic for CR. As for the IDE items, I mentioned it before, but still haven't tried if we can use them. Perhaps it would be a problem, since they are connected and controlled by the master item. PS: No difference in CMOS saved data between 1T and 2T on the abit, except for the system time clock. Edit: I've checked some of the tref values and they seem to match yours. Perhaps they are not board-dependant, but defined by nvidia with the BPL. We can borrow the labels for tref from ultra-d bios. Would save time. Edited November 19, 2019 by I.nfraR.ed Quote
Tzk Posted November 19, 2019 Posted November 19, 2019 (edited) I like your thinking... Do these values look somewhat familiar? I opted to not use values below 516 as even at 100Mhz (DDR200) the default value for 7.8ns ram is 780 cycles. Edited November 19, 2019 by Tzk Quote
I.nfraR.ed Posted November 20, 2019 Posted November 20, 2019 (edited) I want to add the Tref as well, since it is hard to control it within windows in an easy way - no tool can do that at the moment and you have to tinker with wpcredit/rweverything. Auto Precharge can be changed from Memset and NF2 Tweaker, others are also defaulting to the best setting, so Tref in bios is more useful. The ASM code will have to rely on predefined values, since I don't know how to do math operations But still should work. That would be a long "switch". Will abandon the Command Rate option, since I can't make it work, which means I will still need to support 2 bios versions. Making a 2T version is as simple as replacing the BPL module with one from a stock DFI bios, which is 2T by default. I had a quick look at those "view only" options for IDE, but they look different than a regular label. I guess it is because they are connected to the master item and their value is also changed based on the selection and detected value. Which also leads me to the idea to find if it is possible to add other memory settings in the same set which is controlled by Memory Timings [Manual] option item. Edited November 20, 2019 by I.nfraR.ed Quote
Tzk Posted November 20, 2019 Posted November 20, 2019 I'll also stick to two bios versions for CMD. We'd probably need to hook into the bios code way earlier to make it work. As we just need to swap BPL that's the easiest option. And besides that i can only think of a single case when you'd need 2T anyways: max fsb and max mhz runs. For everything else 1T is better. For Tref we must use a big switch... You can't map a Tref value like 4708 (cmos register will contain 1Ah) properly to 6412h through math. So it's simpler to just store the value inside the option rom and use a huge switch. For Trc, Trfc, DS and SR it'll work with math. I mapped Auto to 00h and 1 to 01h. For DS and SR 15 to 0Fh and for Trc and Trfc 31 to 1Fh. I haven't messed with the IDE values yet and will possibly do this when i got Trc, Trfc and Tref working. Quote
I.nfraR.ed Posted November 20, 2019 Posted November 20, 2019 (edited) Yep, I use the value of the option to directly set it. Some bitshifts and that's it. But for Tref will use a switch. Will post the ISA option rom code once ready with everything. Now have to start from scratch an remake the options with the new items. It would be good if I can connect them with the other subtimings which are controlled by the parent "Memory Timings" option, but it might not be possible if a custom code is used in bios for this. I just don't have a good understanding how it works before trying it out. I've decided to place them in the same menu, rather than using one of the free options for a submenu label, because I have only 5 available. Edited November 20, 2019 by I.nfraR.ed Quote
Tzk Posted November 20, 2019 Posted November 20, 2019 (edited) Here's how i did it. My item labels are at the very end of en_code.bin and my item strings and mapping for the option rom are in the textfile. Maybe this saves some work on your end? I haven't written the actual code for the isa option rom yet, that's the next thing i'll do. _EN_CODE-26.BINNew Text Document.txt Edited November 20, 2019 by Tzk 1 Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.