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