Hey all,
For anyone that is interested. I found the latest Microcode update file from Intel specifically for Linux. It was in a a text file format so I write a small proggy to extract out the data and write out the respective binary files for each update.
Each bin file is a multiple of 2kb (most are exactly 2kb) and conform to the specification in the Intel manuals. The process to apply the update is fairly trivial save that you need to apply it for every logical processor (IE: in your trampoline code for smp). In any event I hope someone finds this useful. Refer to Intel manual system programming guide 3a - microcode update facilities.
Link for the original DAT file from Intel:
http://www.johnoconnor.co.za/microcode-20090330.tgz
Link to a RAR of all the extracted BIN files:
http://www.johnoconnor.co.za/Bins.rar
C#.NET 3.5 App to do the extraction:
http://www.johnoconnor.co.za/LXCode2Bin.rar
Let me know if this is helpful, or if you want to share any code for applying the updates etc. This is all towards my system-startup tutorial as mentioned in another thread.
John
Intel Microcode Updating
Re: Intel Microcode Updating
Hey all,
Some more updates on this topic for anyone interested...
You don't have to do anything to support cpu's with hyper-threading, must be applied once per physical/logical cpu otherwise.
I've written some code (it assembles) but haven't had a chance to test it yet that should perform the entire update procedure, all that is needed is to have the bin's in memory and move through them using:
It's written for fasm using:
offset equ
and including the macro file to allow .if/.endif.
If anyone wants to try it out and has some feedback that would be great.
I'll get around to testing it when i'm not at work and update as necessary.
John
Some more updates on this topic for anyone interested...
You don't have to do anything to support cpu's with hyper-threading, must be applied once per physical/logical cpu otherwise.
I've written some code (it assembles) but haven't had a chance to test it yet that should perform the entire update procedure, all that is needed is to have the bin's in memory and move through them using:
Code: Select all
;##############################################################################################################################
;
; VX Platform v1.0
; - Intel CPU Microcode update loader v1.0
; Author: John Hankinson
; Date: 2010-02-01
;
;##############################################################################################################################
_imc_update_checksum dd ?
_imc_update_datasize dd ?
_imc_update_totalsize dd ?
_imc_update_processorSignature dd ?
_imc_update_processorFlags dd ?
_imc_update_extsigSize dd ?
_imc_update_extsigCount dd ?
_imc_cpu_processorSignature dd ?
_imc_cpu_platformID dd ?
_imc_cpu_currentUpdateVer dd ?
;==============================================================================================================================
; Real Mode Microcode update loader.
; -> IN: ES:EDI points to update packet.
; -> OUT: EAX = 1[fail] or 0[success].
; -> Update packet cannot cross a segment boundary and must be 16byte aligned.
;==============================================================================================================================
cpu_microcode_update:
; Ensure all global values are reset.
mov dword [_imc_update_checksum],0
mov dword [_imc_update_datasize],0
mov dword [_imc_update_totalsize],0
mov dword [_imc_update_processorSignature],0
mov dword [_imc_update_processorFlags],0
mov dword [_imc_update_extsigSize],0
mov dword [_imc_update_extsigCount],0
; Get the current update version or 0 if none.
mov eax,01h
CPUID ; Ensure the MSR is loaded so we can read it.
mov ecx,MSR_IA32_BIOS_SIGN_ID
xor edx,edx
xor eax,eax
RDMSR
mov [_imc_cpu_currentUpdateVer],edx
; Ensure Update's Header Version is 00000001h.
mov eax,[es:edi]
.if eax <> 1
mov eax,1
ret ; If the update header is not 1 then return.
.endif
; Ensure that this update's revision is > than our CPUs current loaded one.
mov eax,[es:edi+4]
cmp eax,[_imc_cpu_currentUpdateVer]
jge short verOk
mov eax,1 ; Version is older - don't continue.
ret
; Get the update's size values.
verOk:
mov eax,[es:edi+16] ; Get the update checksum. this + all dwords of update should = 0.
mov ebx,[es:edi+28] ; Get the data size in bytes (if 0 then size is 2000 bytes).
mov ecx,[es:edi+32] ; Get total size of update in bytes (= head+data+optional ext. sig. table).
; If the data size is 0, then it's assumed to be 2000.
.if ebx = 0
mov ebx,2000
mov ecx,(2000+48)
.endif
mov [_imc_update_checksum],eax
mov [_imc_update_datasize],ebx
mov [_imc_update_totalsize],ecx
; Determine if there is an extended signature table and if so the count.
sub ecx,ebx
.if ecx > 48
mov [_imc_update_extsigSize],ecx
mov eax,[_imc_update_datasize]
add eax,48
mov eax,[es:edi+eax] ; Location of Extended Signature Count.
mov [_imc_update_extsigCount],eax
.endif
; Validate the update's checksum.
xor eax,eax
mov ecx,[_imc_update_totalsize]
shr ecx,2 ; Size in bytes now dwords.
push edi
validate_checksum:
add eax,[es:edi]
add edi,4
dec ecx
jnz short validate_checksum
pop edi
.if eax <> 0
mov eax,1 ; Checksum validation failed.
ret
.endif
; Get CPU type, family, model, stepping id.
mov eax,1 ; | 31 - 28 | 27 - 20 | 19 - 16 | 15 - 14 | 13 - 12 | 11 - 8 | 7 - 4 | 3 - 0 |
CPUID ; eax will contain: | | ext family id | ext model id | | | family id | model | stepping |
mov [_imc_cpu_processorSignature],eax
; Get the update data's Processor Signature.
mov ebx,[es:edi+12]
mov [_imc_update_processorSignature],ebx
; Ensure that we can find a matching signature between the update and our CPU.
.if eax <> ebx
mov ebx,[_imc_update_extsigSize]
.if ebx <> 0
mov ecx,[_imc_update_extsigCount]
xor ebx,ebx
push edi
add edi,[_imc_update_datasize]
add edi,(48+20)
checkExtSigs:
mov edx,[es:edi]
.if eax = edx
mov ebx,1 ; Found a matching signature.
.endif
add edi,12 ; Move to next extended signature entry.
dec ecx
jnz short checkExtSigs
pop edi
.if ebx = 1
jmp short processorSignaturesMatch
.endif
.endif
mov eax,1
ret ; If the processor signature of the update doesn't match our CPU then return.
.endif
; Read IA32_PLATFORM_ID MSR (bits 50-52).
processorSignaturesMatch:
mov ecx,MSR_IA32_PLATFORM_ID
RDMSR
mov [_imc_cpu_platformID],edx
; Read the Update's Processor Flags.
mov ebx,[es:edi+24] ; Read processor flags from the update.
mov [_imc_update_processorFlags],ebx
; Ensure that the processor flags match.
mov eax,1
mov ecx,[_imc_cpu_platformID]
and ecx,00000000000111000000000000000000b ; Keep bits 50-52 of the MSR.
shr ecx,18
shl eax,cl
mov ebx,eax
and eax,[_imc_update_processorFlags]
.if eax <> 0
jmp short load_update ; The primary processor flags match.
.endif
; Now loop through extended processorFlags and test.
mov eax,ebx
mov ebx,[_imc_update_extsigSize]
.if ebx <> 0
mov ecx,[_imc_update_extsigCount]
xor ebx,ebx
push edi
add edi,[_imc_update_datasize]
add edi,(48+20)
checkExtFlags:
mov edx,[es:edi+4]
and edx,eax
.if edx <> 0
mov ebx,1 ; Found a matching flags/platform id.
.endif
add edi,12 ; Move to next extended signature entry.
dec ecx
jnz short checkExtFlags
pop edi
.if ebx = 1
jmp short load_update
.endif
.endif
mov eax,1 ; No matching processor flags so fail.
ret
; Force processor to load the microcode update.
load_update:
xor eax,eax
mov ax,es
shl eax,4
add eax,edi
add eax,48 ; Skip the header (point straight at update data).
xor edx,edx
mov ecx,MSR_IA32_BIOS_UPDT_TRIG
WRMSR
; Confirm that the update revision matches the update.
mov eax,01h
CPUID
mov ecx,MSR_IA32_BIOS_SIGN_ID
xor edx,edx
xor eax,eax
RDMSR
.if edx <> dword [_imc_cpu_currentUpdateVer]
mov eax,1
ret ; Revision's differ / update must have failed.
.endif
xor eax,eax
ret
offset equ
and including the macro file to allow .if/.endif.
If anyone wants to try it out and has some feedback that would be great.
I'll get around to testing it when i'm not at work and update as necessary.
John