1 /* SPDX-License-Identifier: GPL-2.0-only */
4 * input %esp: return address (not pointer to return address!)
5 * clobber the content of eax, ebx, ecx, edx, esi, edi, and ebp
8 #include <cpu/x86/post_code.h>
9 #include <cpu/x86/msr.h>
11 #define CBFS_FILE_MAGIC 0
12 #define CBFS_FILE_LEN (CBFS_FILE_MAGIC + 8)
13 #define CBFS_FILE_TYPE (CBFS_FILE_LEN + 4)
14 #define CBFS_FILE_CHECKSUM (CBFS_FILE_TYPE + 4)
15 #define CBFS_FILE_OFFSET (CBFS_FILE_CHECKSUM + 4)
17 #define HEADER_VER_OFFSET 0
18 #define UPDATE_VER_OFFSET 4
20 #define PROCESSOR_SIG_OFFSET 12
21 #define CHKSUM_OFFSET 16
22 #define LOADER_REV_OFFSET 20
23 #define PROCESSOR_FLAG 24
24 #define DATA_SIZE_OFFSET 28
25 #define TOTAL_OFFSET 32
26 #define HEADER_SIZE 48
29 * The microcode header is 48 bytes wide and has the following
31 * Header Version : 32bit
32 * Update Revision : 32bit
34 * Processor Signature : 32bit
36 * Loader Revision : 32bit
37 * Processor Flags : 32bit
42 * We only check if the Processor signature and flags match and check
43 * if the revision of the update is newer than what is installed
48 .global update_bsp_microcode
51 /* Keep return address */
53 /* find microcodes in cbfs */
54 leal microcode_name, %esi
59 /* restore return address */
63 je end_microcode_update
64 movl CBFS_FILE_OFFSET(%eax), %ebx
69 movl CBFS_FILE_LEN(%eax), %edi
74 * Microcode revision -> %ebx
75 * Processor flags -> %ebp
76 * Current installed microcode revision -> %edx
81 * pf = 1 << ((msr.hi >> 18) & 7) */
82 movl $IA32_PLATFORM_ID, %ecx
87 /* needs to be %cl for shl */
92 /* Fetch the current microcode revision*/
95 movl $IA32_BIOS_SIGN_ID, %ecx
100 /* Processor family+model signature=cpuid_eax(1) */
103 movl $IA32_BIOS_SIGN_ID, %ecx
106 check_microcode_entry:
107 /* Test if header revision is non zero */
108 cmpl $0, HEADER_VER_OFFSET(%esi)
109 je end_microcode_update
111 /* Processor family+model signature=cpuid_eax(1) */
112 cmpl PROCESSOR_SIG_OFFSET(%esi), %ebx
115 /* Processor flags */
116 test PROCESSOR_FLAG(%esi), %ebp
119 /* Check if revision is higher than current */
120 cmpl UPDATE_VER_OFFSET(%esi), %edx
121 /* Don't upgrade if already greater or equal */
122 jge end_microcode_update
124 /* Do actual update */
126 addl $HEADER_SIZE, %eax
128 movl $IA32_BIOS_UPDT_TRIG, %ecx
131 jmp end_microcode_update
134 movl TOTAL_OFFSET(%esi), %eax
137 /* Newer microcode updates include a size field, whereas older
138 * containers set it at 0 and are exactly 2048 bytes long */
146 ja check_microcode_entry
148 end_microcode_update:
152 .string "cpu_microcode_blob.bin"
154 _update_bsp_microcode_end: