I have found a somewhat unique case where phoenixtool185 cant mod an old style dell bios. The machine in question is a Dell Precision 470, dual xeon machine, the pheonixtool seemed to work fine when it had a pair of single core xeons installed (although now i have learned a bit more about the bios id like to check that). Replacing the single core Xeons with a pair of Paxville SL8MA dual core xeons, resulted in windows7 blue screening and stuttering and problems under ubuntu. Initially i thought i had killed the motherboard so one ebay replacement later and all was good until the bios was flashed then it was back to blue-screen crashing. So it was definitely a problem with the patch, re-flashing a clean bios and dumping the ACPI tables revealed that there were extra entry's for the extra cores+multithreading: Code: Signature"RSD PTR " Checksum0x51 (81) OEM ID"DELL " Revision0x00 (0) - ACPI 1.0 RSDT Address0x000FCB55 Root System Description Table: 0x000FCB55 52 53 44 54 64 00 00 00 01 B1 44 45 4C 4C 20 20RSDTd.....DELL 57 53 20 34 37 30 20 00 07 00 00 00 41 53 4C 20WS 470 .....ASL 61 00 00 00 B9 CB 0F 00 FE 7E FC FF 2D CC 0F 00a........~..-... D7 CC 0F 00 FF CC 0F 00 66 CD 0F 00 A4 CD 0F 00........f....... 40 AC E8 BF 49 B0 E8 BF 52 B4 E8 BF 5B B8 E8 [email protected]...[... 64 BC E8 BF 6D C0 E8 BF 76 C4 E8 BF 7F C8 E8 BFd...m...v....... 88 CC E8 BF .... Signature"RSDT" Length0x00000064 (100) Revision0x01 (1) Checksum0xB1 (177) OEM ID"DELL " OEM Table ID"WS 470 " OEM Revision0x00000007 (7) Creator ID"ASL " Creator Revision0x00000061 (97) Entry00x000FCBB9 (FACP) Entry10xFFFC7EFE (SSDT) Entry20x000FCC2D (APIC) Entry30x000FCCD7 (BOOT) Entry40x000FCCFF (ASF!) Entry50x000FCD66 (MCFG) Entry60x000FCDA4 (HPET) Entry70xBFE8AC40 (SSDT) Entry80xBFE8B049 (SSDT) Entry90xBFE8B452 (SSDT) Entry100xBFE8B85B (SSDT) Entry110xBFE8BC64 (SSDT) Entry120xBFE8C06D (SSDT) Entry130xBFE8C476 (SSDT) Entry140xBFE8C87F (SSDT) Entry150xBFE8CC88 (SSDT) These extra SSDT entrys now fill the RSDT space so there is no free space left to add a slic entry, and it no simple mod to move the RSDT as I dont know where in the bios the extra tables and larger length get written to the rsdt. In the bios the table initially has a length of 0x40 but this is increased presumably by the same code that adds the extra SSDT entrys. So I had an idea, move the FACP table that follows and use the extra free space to extend the rsdt. Comparing the table in the bios to that of a running system showed that there were 2 dynamic elements + the checksum in the FACP: Firmware Control0xBFE8AC00 - FACS DSDT Address0xFFFC4DE8 - DSDT Mooching through the code in module 1 I came across the same code as in all dell bios's where the tables are fixed up and the checksums calculated: Code: seg000:3B2B mov cs:FACP_slot_2, esi ; 2nd empty entry in FACP seg000:3B31 mov cs:FACP_slot_1, edi ; 1st empty entry in FACP <snip some code> seg000:3BD3 mov si, offset aFacpt ; FACP table start seg000:3BD6 lea di, [si+9] ; di < checksum location seg000:3BD9 mov cx, cs:[si+4] ; cx < table size seg000:3BDD call fix_checksum ; Fix table checksum That seems to cover all the places you'd have to patch module 1 to move the FACP table, so i gave it a bash but failed, Im still unsure of the reason as I thought I had found a dos tool to let me dump ram but for some reason it appears it didnt save the dump i made to let me debug it. From what i rember of it the FACP table was successfully updated but for some reason the RSDT table didnt get populated with the the extra ssdt tables, I did increase the stored length of the rsdt table by 4 bytes without clearing the old facp table so that may have been the cause of the error if it was trying to parse bogus data and failing, ill look at that some more soon. In the meantime if anyone can recommend a dos tool to dump sections of memory it would be a great help in debugging. This following bit only makes sense if you inderstand that the RSDT table in the bios is different to that of the running system in that its length and some table entrys are created dynamically at boot time, the entrys you see in the flash are the fixed ones and the space after them is used to hold entrys that vary based on the number of CPU cores. The one in flash looks like: Code: Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F 00004B50 52 53 44 54 40 00 00 00 01 00 44 [email protected] 00004B60 45 4C 4C 20 20 57 53 20 34 37 30 20 00 07 00 00 ELL WS 470 .... 00004B70 00 41 53 4C 20 61 00 00 00 B9 CB 0F 00 00 00 00 .ASL a...¹Ë..... 00004B80 00 2D CC 0F 00 D7 CC 0F 00 FF CC 0F 00 66 CD 0F .-Ì..×Ì..ÿÌ..fÍ. 00004B90 00 A4 CD 0F 00 00 00 00 00 00 00 00 00 00 00 00 .¤Í............. 00004BA0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00004BB0 00 00 00 00 00 00 00 00 00 ......... With the length set to 40 for the entrys that are there, the freespace is used for dynamic entrys up to a maximum length of 0x64 if you have 8 cpus (2xdual core chips with hyperthreading) Whilst hunting through the modules trying to find where the extra ssdt table get populated, and in particular where the length byte gets increased and which bit of code sets the offset for where the table entrys get updated. My thinking was if i were to merely increase the rsdt table length by 4 in the flash the code that adds the extra tables should just increase this number and i could add the slic at the end in what used to be the first 4 bytes of the FACP, however if i were to change the CPU's again to single core chips the slic would no longer be at the end of the entrys and the extra entry would just point to 0x00. So ideally I want to increase the size of the empty table by 4 add the new entry for the slic in the first empty slot then find the code that adds the dynamic tables and increase the offset at which they are added by 4, so the slic isnt at the end, this way whatever CPU is fitted it *should* just work. Anyway module 7 looks like a likely candidate for the code that populates these tables i might have found the code that adds the cpu specific SSDT entrys but im having trouble understanding it, i think the following is the bit im looking for: Code: seg000:A84F sub_A84F proc near ; CODE XREF: seg000:A1FDp seg000:A84F call check_ACPI_tables seg000:A852 jb short locret_A88A seg000:A854 push esi seg000:A856 lea esi, unk_D9C8 seg000:A85B bts word ptr [esi+10000h], 0 seg000:A864 lea edi, unk_D9D2 seg000:A869 mov edi, [edi+10000h] seg000:A871 add edi, 40h ; '@' ;i think this might be the offset to begin writing entrys seg000:A875 lea esi, unk_D9EE seg000:A87A mov [esi+10000h], edi seg000:A882 pop esi seg000:A884 call Setup_ssdt? seg000:A887 call sub_A88B Any thoughts on this, or ideas on how to load the modules in ida so i can makes some sense on how they all interact?
Just to add i think i am on the right track, and it might be possible to just move the RSDT like the other mods, in module 7 i found the 2 routines for checking and calculating the ACPI table checksums: Code: chk_checksum proc near ; CODE XREF: check_ACPI_tables+7Bp seg000:B27A ; check_ACPI_tables+A6p ... seg000:B27A push edi seg000:B27C xor al, al ; set al to 0 seg000:B27E seg000:B27E loc_B27E: ; CODE XREF: chk_checksum+Aj seg000:B27E add al, es:[edi] seg000:B282 inc edi seg000:B284 loop loc_B27E seg000:B286 or al, al ; Set zero flag if al=0 seg000:B288 pop edi seg000:B28A retn seg000:B28A chk_checksum endp seg000:B28A seg000:B28B seg000:B28B ; =============== S U B R O U T I N E ======================================= seg000:B28B seg000:B28B seg000:B28B Calculate_checksum proc near ; CODE XREF: sub_A88B+16Bp seg000:B28B ; sub_AC8B+249p ... seg000:B28B push ecx seg000:B28D push ax seg000:B28E xor al, al seg000:B290 mov es:[edi+9], al ; set checksum to 0 seg000:B295 mov ecx, es:[edi+4] seg000:B29B call chk_checksum ; returns the sum of a tables bytes in al seg000:B29B ; should return 0 if checksum is good seg000:B29E neg al ; calculate difference between sum of bytes and 0 seg000:B2A0 mov es:[edi+9], al ; and save it in the checksum byte seg000:B2A5 clc ; clear the carry flag set by the neg seg000:B2A6 pop ax seg000:B2A7 pop ecx seg000:B2A9 retn seg000:B2A9 Calculate_checksum endp
About microcode update module again: (Example: for D510, D610, D810 file named 02-02-0E.rom by Apokrif's tool, or 0E-02.rom by Andy's tool) If I use Apokrif's Split.exe utility to extract the BIOS I get a microcode file size of 16 kB. If I use Andy's Phoenixtool utility i get the file size 58 kB. Code: 02-02-0E.rom Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F 00000000 0A 00 94 06 20 00 56 00 30 42 41 42 95 06 20 00 ” V 0BAB• 00000010 26 08 31 42 41 42 95 06 80 00 F6 0F 31 42 43 42 & 1BAB• Ђ ц 1BCB 00000020 D0 06 20 00 C6 17 30 41 4F 44 D1 06 20 00 96 1F Р Ж 0AODС – 00000030 31 41 4F 44 D2 06 20 00 66 27 32 41 4F 44 D6 06 1AODТ f'2AODЦ 00000040 20 00 36 2F 31 42 4F 44 D8 06 20 00 06 37 30 43 6/1BODШ 70C 00000050 4F 44 ...... 0E-02.rom Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F 00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00000010 00 56 00 42 41 42 95 00 00 00 00 00 00 00 26 00 V BAB• & 00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00000030 00 00 00 00 00 F6 00 00 00 00 00 00 00 00 00 00 ц 00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00000050 00 00 00 00 00 00 00 00 00 00 00 00 06 20 00 C6 Ж 00000060 17 30 41 4F 44 D1 06 20 00 96 00 00 00 00 00 00 0AODС – Red: Pieces of code is the same i.t.c. What's the catch? Andy, Can you improve of decompression algorithm or i'm not understand something? Thanks.
@aascut I noticed a similar thing the other day when looking at the DSDT module ( 00-09-15.rom ) module 15 is an uncompressed module, when you split the bios with Apokrif's tool it doesn't decompress the modules it just splits them out into separate compressed modules, which you have to decompress separately. Andy's tool splits and decompresses all the modules (including those that shouldn't be decompressed such as the DSDT) so if you look at any raw uncompressed modules using Andy's tool they will be wrong. I don't think this has any effect on patching bios's as the only modules changed in the patch are 01 and 02 which are both compressed, the rest remain untouched, however it will cause problems if you try to use Andy's tool to change uncompressed modules. I havent seen the bios code responsible for unpacking the bios at boot but I'm guessing it must know if a module is compressed or not if there is some sort of module index in the bios somewhere, perhaps it could be used to ensure modules are split and decompressed or just split as appropriate.
I totally agree with you. I will look for code decompression in the BIOS. en4rab,gabiz_ro Thanks for info! Now I understand. Use these utilities for modifications must be very careful!
Result! While this is likely only applicable so very few Dell machines that are old enough to not have a SLIC but new enough to support multiple/multicore CPU's I have worked out how to deal with a variable number of dynamic SSDT's at the end of the RSDT table. Code: Root System Description Pointer: 0x000FEBF0 52 53 44 20 50 54 52 20 5E 44 45 4C 4C 20 20 00RSD PTR ^DELL . 20 F3 0F 00 ... Signature"RSD PTR " Checksum0x5E (94) OEM ID"DELL " Revision0x00 (0) - ACPI 1.0 RSDT Address0x000FF320 Root System Description Table: 0x000FF320 52 53 44 54 68 00 00 00 01 84 44 45 4C 4C 20 20RSDTh.....DELL 4D 30 39 20 20 20 20 00 07 00 00 00 41 53 4C 20M09 .....ASL 61 00 00 00 B9 CB 0F 00 B3 7B FC FF 2D CC 0F 00a........{..-... D7 CC 0F 00 FF CC 0F 00 66 CD 0F 00 A4 CD 0F 00........f....... A0 F3 0F 00 44 AC E8 BF 4D B0 E8 BF 56 B4 E8 BF....D...M...V... 5F B8 E8 BF 68 BC E8 BF 71 C0 E8 BF 7A C4 E8 BF_...h...q...z... 83 C8 E8 BF 8C CC E8 BF ........ Signature"RSDT" Length0x00000068 (104) Revision0x01 (1) Checksum0x84 (132) OEM ID"DELL " OEM Table ID"M09 " OEM Revision0x00000007 (7) Creator ID"ASL " Creator Revision0x00000061 (97) Entry00x000FCBB9 (FACP) Entry10xFFFC7BB3 (SSDT) < added by code in module 01 Entry20x000FCC2D (APIC) Entry30x000FCCD7 (BOOT) Entry40x000FCCFF (ASF!) Entry50x000FCD66 (MCFG) Entry60x000FCDA4 (HPET) < last fixed table in RSDT Entry70x000FF3A0 (SLIC) < note it appears before the variable number of dynamic tables Entry80xBFE8AC44 (SSDT) < these are added and the length of RSDT is changed by code in module 0B Entry90xBFE8B04D (SSDT) Entry100xBFE8B456 (SSDT) Entry110xBFE8B85F (SSDT) Entry120xBFE8BC68 (SSDT) Entry130xBFE8C071 (SSDT) Entry140xBFE8C47A (SSDT) Entry150xBFE8C883 (SSDT) Entry160xBFE8CC8C (SSDT) In the case of the Dell precision 470 the ACPI tables appear to be setup in 2 stages, the first stage is already discussed in this thread, where the bios loader unpacks module 01 to 0x000F0000 and module 02 to 0x000F8000, the code in module 1 inserts the address of the first SSDT table into the second slot in the RSDT and fixes up the checksums of all the tables, it does not change the RSDT table size. Module 0B appears to complete the ACPI setup where after the number of CPU's has been evaluated it adds SSDT tables for each of the cores (physical and virtual hyperthreading ones) and one for CPU power management, this code increases the size of the RSDT table as appropriate and recalculates the checksum of the larger table. Importantly it doesnt access the ACPI tables using fixed offsets, rather the code in module 0B first scans memory for the RSD PTR and uses the address in the PTR to find and check the integrity of ACPI tables. below is the main routine responsible for this secondary setup: Code: seg000:A84F sub_A84F proc near ; CODE XREF: seg000:A1FDp seg000:A84F call check_ACPI_tables seg000:A852 jb short locret_A88A seg000:A854 push esi seg000:A856 lea esi, unk_D9C8 seg000:A85B bts word ptr [esi+10000h], 0 seg000:A864 lea edi, unk_D9D2 seg000:A869 mov edi, [edi+10000h] seg000:A871 add edi, 40h ; '@' ; Set offset into RSDT table to begin adding CPU seg000:A871 ; specific SSDT tables seg000:A875 lea esi, unk_D9EE seg000:A87A mov [esi+10000h], edi seg000:A882 pop esi seg000:A884 call Setup_SSDT seg000:A887 call sub_A88B seg000:A88A seg000:A88A locret_A88A: ; CODE XREF: sub_A84F+3j seg000:A88A retn seg000:A88A sub_A84F endp Note, the line "add edi, 40h" this sets the offset into the RSDT table to begin adding the dynamic SSDT's, the fixed part of the RSDT in bios has a length of 40 so this points to the start of the free space between the RSDT and the FACP that follows it. The code that extends the RSDT reads in the existing length of the table then adds on the appropriate length depending on how many tables are added. All this means it is relatively easy to add a SLIC table in a manner that will work independantly of the number of cpu's/cores are fitted to the machine. Initally the method is the same as the way you would mod a dell bios with no free space in the RSDT, copy the RSDT and paste it in the free space near the end of the 02 module, edit the address in the RSD PTR to point to the new table, leave at least 4 bytes after this new table to allow you to extend it and add an extra entry then paste the SLIC table in. Now add the address of the SLIC into the RSDT in the first free slot after the fixed tables (where the first CPU specific SSDT would go), increase the length dword by 4 (in this case from 0x00000040 to 0x00000044) and change the 4 bytes after the RSDT table from FF to 00, and edit all instances of the OEM Table ID to match the one in the SLIC. The RSDT table should now look something like this: Code: Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F 00007320 52 53 44 54 44 00 00 00 01 00 44 45 4C 4C 20 20 RSDTD.....DELL 00007330 4D 30 39 20 20 20 20 00 07 00 00 00 41 53 4C 20 M09 .....ASL 00007340 61 00 00 00 B9 CB 0F 00 00 00 00 00 2D CC 0F 00 a...¹Ë......-Ì.. 00007350 D7 CC 0F 00 FF CC 0F 00 66 CD 0F 00 A4 CD 0F 00 ×Ì..ÿÌ..fÍ..¤Í.. 00007360 A0 F3 0F 00 00 00 00 00 00 00 00 00 00 00 00 00 *ó.............. 00007370 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00007380 00 00 00 00 00 00 00 00 FF FF FF FF FF FF FF FF ........ÿÿÿÿÿÿÿÿ 00007390 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 000073A0 53 4C 49 43 76 01 00 00 01 8A 44 45 4C 4C 20 20 SLICv....ŠDELL 000073B0 4D 30 39 20 20 20 20 00 12 0C D8 27 41 53 4C 20 M09 ...Ø'ASL Optionally you can null out the original RSDT to improve compression. This is all the changes needed to module 02, the next post will list the changes needed to module 01 and 0B
Now the new tables are setup in module 02, but the code in module 01 adds the first SSDT entry into the RSDT and calculates its checksum and it does this using fixed addresses so these need to be patched to point to the relocated RSDT. The code that does this looks like: Code: seg000:3B68 add esi, ebx seg000:3B6B mov cs:RSDT_slot_2, esi ; SSDT Ptr address in RSDT seg000:3B71 mov si, offset aBoot ; BOOT table start The second line above is what writes the address of the first SSDT table into the second slot of the RSDT table, in hex this looks like: 66 03 F3 66 2E 89 36 7D CB BE D7 CC The address to write to needs to be edited to point the the second slot of the relocated RSDT table, using the example at the and of the last post this address is 7348 (+ 8000 to account for the offset where module 02 is loaded) = F348, this is stored reversed in the binary because the x86 architecture is brain damaged so you would have to replace 7D CB with 48 F3. That is the dynamic SSDT dealt with, now the routine that fixes the checksum needs to be patched in a similar manner: Code: seg000:3BC6 mov si, 0CB55h ; RSDT table start seg000:3BC9 lea di, [si+9] ; di < checksum location seg000:3BCC mov cx, cs:[si+4] ; cx < table size seg000:3BD0 call fix_checksum ; Fix table checksum in the hex this first instruction looks like BE 55 CB, again calculate the address of the start of the relocated RSDT table as above, reverse the bytes and change the 55 CB to the appropriate address. That is all of module 01 done, the last thing to do is the extra step that makes this all work, module 0B (in earlier posts i referred to this as module 07 as i got muddled up with the naming between apokrifs tools and andyp's, in these 2 posts im referring to the module type so ob would show as 00-07-0B.bin using apokrifs tools, 7th module in the bios, type 0B.) Because this module scans for the ACPI tables there arent any fixed addresses to patch, the only thing that needs changing is the single byte that sets the offset into the RSDT table to start writing the dynamic SSDT's: Code: seg000:A871 add edi, 40h (see top of previous post for a fuller paste of this code) in hex this shows as 66 83 C7 40 just change the 40 to 44 to allow for the added SLIC, job done. Now youd just have to recompress these patched modules, reintergrate then into the .hdr and stuff the .hdr back in the exe, apokrifs tools are excellent for this, I havent tried doing this with andyp's phoenixtool. This is all probably unimportant in the grand scale of things as i suspect there are very few Dell's this would be applicable to, im guessing most multi CPU/multi core capable dells will have a SLIC already.
Will someone answer please? aascut and apokrif I am sorry. I think it's almost done now so please help me just a little more. Thanks for all your previous help.
WIND0WS 7 I do not know the theory. I'm studying this and I can not help now. As soon as understand, I will tell you.
Hey kizwan, where's that calculator you showed from? It's not in HxD or WinHex After the changes I'll need to fix the CRC32 of entire .hdr file back to 0xFFFFFFFF by changing the last 4 bytes in my .hdr with fakecrc or w/e won't I? Oh and which app/tool does that (xxxxx.EXE /writeromfile)? Thank you very much!
Hi WINDOWS 7, Usually BIOS image downloaded from manufacturer website is in .EXE. For Dell BIOS, to obtain the .HDR & .ROM file, execute the .EXE file in Windows Command Prompt:- To extract .HDR file: xxxxx.EXE /writehdrfile To extract .ROM file: xxxxx.EXE /writeromfile Note: Execute the above commands in guest OS (in VMware or any virtual machine software). You don't want to accidentally flash BIOS with wrong BIOS image. Some Dell computer use Phoenix BIOS & if you try to execute the above commands, you'll only execute the BIOS update utility. I have one task for you, download "Beyond Compare 3" software. You should be able to download trial version. Use it to compare both .HDR & .ROM files. You'll see the difference between the two files are the .HDR file have extra at the beginning (HEADER) & at the end (FOOTER). The HEADER is the BIOS header while the FOOTER is where checksum is located (to be exact the checksum of the .ROM file). If you can see that, you'll understand where the checksum is located. The calculator I'm using is Windows Calculator which available in all Windows operating system.