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:
Arthur Heymans 2018-06-13 15:54:35 +02:00 committed by Kyösti Mälkki
parent 2d324cafd8
commit 2e658f8edf
1 changed files with 162 additions and 0 deletions

View File

@ -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: