src/cpu/microcode: Add code to update microcode in assembly
Add code to update microcode from cbfsfiles using assembly. Change-Id: I8bd192f3f345651db0010239f99293ae63b00652 Signed-off-by: Arthur Heymans <arthur@aheymans.xyz> Reviewed-on: https://review.coreboot.org/c/27091 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Patrick Rudolph <siro@das-labor.org> Reviewed-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
This commit is contained in:
parent
2d324cafd8
commit
2e658f8edf
|
@ -0,0 +1,162 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the coreboot project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2018 Arthur Heymans <arthur@aheymans.xyz>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* input %esp: return address (not pointer to return address!)
|
||||||
|
* clobber the content of eax, ebx, ecx, edx, esi, edi, and ebp
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cpu/x86/post_code.h>
|
||||||
|
#include <cpu/x86/msr.h>
|
||||||
|
#include <arch/x86/walkcbfs.S>
|
||||||
|
|
||||||
|
#define HEADER_VER_OFFSET 0
|
||||||
|
#define UPDATE_VER_OFFSET 4
|
||||||
|
#define DATE_OFFSET 8
|
||||||
|
#define PROCESSOR_SIG_OFFSET 12
|
||||||
|
#define CHKSUM_OFFSET 16
|
||||||
|
#define LOADER_REV_OFFSET 20
|
||||||
|
#define PROCESSOR_FLAG 24
|
||||||
|
#define DATA_SIZE_OFFSET 28
|
||||||
|
#define TOTAL_OFFSET 32
|
||||||
|
#define HEADER_SIZE 48
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The microcode header is 48 bytes wide and has the following
|
||||||
|
* structure:
|
||||||
|
* Header Version : 32bit
|
||||||
|
* Update Revision : 32bit
|
||||||
|
* Date : 32bit
|
||||||
|
* Processor Signature : 32bit
|
||||||
|
* Checksum : 32bit
|
||||||
|
* Loader Revision : 32bit
|
||||||
|
* Processor Flags : 32bit
|
||||||
|
* Data Size : 32bit
|
||||||
|
* Total Size : 32bit
|
||||||
|
* Reserved : 96bit
|
||||||
|
*
|
||||||
|
* We only check if the Processor signature and flags match and check
|
||||||
|
* if the revision of the update is newer than what is installed
|
||||||
|
*/
|
||||||
|
|
||||||
|
.section .text
|
||||||
|
.global update_bsp_microcode
|
||||||
|
|
||||||
|
update_bsp_microcode:
|
||||||
|
/* Keep return address */
|
||||||
|
movl %esp, %edx
|
||||||
|
/* find microcodes in cbfs */
|
||||||
|
leal microcode_name, %esi
|
||||||
|
movl $1f, %esp
|
||||||
|
jmp walkcbfs_asm
|
||||||
|
|
||||||
|
1:
|
||||||
|
/* restore return address */
|
||||||
|
movl %edx, %esp
|
||||||
|
|
||||||
|
cmpl $0, %eax
|
||||||
|
je end_microcode_update
|
||||||
|
movl CBFS_FILE_OFFSET(%eax), %ebx
|
||||||
|
bswap %ebx
|
||||||
|
addl %eax, %ebx
|
||||||
|
movl %ebx, %esi
|
||||||
|
|
||||||
|
movl CBFS_FILE_LEN(%eax), %edi
|
||||||
|
bswap %edi
|
||||||
|
addl %esi, %edi
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Microcode revision -> %ebx
|
||||||
|
* Processor flags -> %ebp
|
||||||
|
* Current installed microcode revision -> %edx
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Processor family+model signature=cpuid_eax(1) */
|
||||||
|
movl $1, %eax
|
||||||
|
cpuid
|
||||||
|
movl %eax, %ebx
|
||||||
|
|
||||||
|
/* Processor flags
|
||||||
|
* rdmsr 0x17
|
||||||
|
* pf = 1 << ((msr.hi >> 18) & 7) */
|
||||||
|
movl $IA32_PLATFORM_ID, %ecx
|
||||||
|
rdmsr
|
||||||
|
shr $18, %edx
|
||||||
|
andl $7, %edx
|
||||||
|
movl $1, %eax
|
||||||
|
/* needs to be %cl for shl */
|
||||||
|
movl %edx, %ecx
|
||||||
|
shl %cl, %eax
|
||||||
|
movl %eax, %ebp
|
||||||
|
|
||||||
|
/* Fetch the current microcode revision*/
|
||||||
|
xorl %eax, %eax
|
||||||
|
xorl %edx, %edx
|
||||||
|
movl $IA32_BIOS_SIGN_ID, %ecx
|
||||||
|
wrmsr
|
||||||
|
movl $0x1, %eax
|
||||||
|
cpuid
|
||||||
|
movl $IA32_BIOS_SIGN_ID, %ecx
|
||||||
|
rdmsr
|
||||||
|
|
||||||
|
check_microcode_entry:
|
||||||
|
/* Test if header revision is non zero */
|
||||||
|
cmpl $0, HEADER_VER_OFFSET(%esi)
|
||||||
|
je end_microcode_update
|
||||||
|
|
||||||
|
/* Processor family+model signature=cpuid_eax(1) */
|
||||||
|
cmpl PROCESSOR_SIG_OFFSET(%esi), %ebx
|
||||||
|
jne next_entry
|
||||||
|
|
||||||
|
/* Processor flags */
|
||||||
|
cmpl PROCESSOR_FLAG(%esi), %ebp
|
||||||
|
jne next_entry
|
||||||
|
|
||||||
|
/* Check if revision is higher than current */
|
||||||
|
cmpl UPDATE_VER_OFFSET(%esi), %edx
|
||||||
|
/* Don't upgrade if already greater or equal */
|
||||||
|
jge end_microcode_update
|
||||||
|
|
||||||
|
/* Do actual update */
|
||||||
|
movl %esi, %eax
|
||||||
|
addl $HEADER_SIZE, %eax
|
||||||
|
xorl %edx, %edx
|
||||||
|
movl $IA32_BIOS_UPDT_TRIG, %ecx
|
||||||
|
wrmsr
|
||||||
|
|
||||||
|
jmp end_microcode_update
|
||||||
|
|
||||||
|
next_entry:
|
||||||
|
movl TOTAL_OFFSET(%esi), %eax
|
||||||
|
cmpl $0, %eax
|
||||||
|
jne 1f
|
||||||
|
/* Newer microcode updates include a size field, whereas older
|
||||||
|
* containers set it at 0 and are exactly 2048 bytes long */
|
||||||
|
addl $2048, %esi
|
||||||
|
jmp check_end
|
||||||
|
1:
|
||||||
|
addl %eax, %esi
|
||||||
|
|
||||||
|
check_end:
|
||||||
|
cmpl %esi, %edi
|
||||||
|
ja check_microcode_entry
|
||||||
|
|
||||||
|
end_microcode_update:
|
||||||
|
jmp *%esp
|
||||||
|
|
||||||
|
microcode_name:
|
||||||
|
.string "cpu_microcode_blob.bin"
|
||||||
|
|
||||||
|
_update_bsp_microcode_end:
|
Loading…
Reference in New Issue