blob: 5173ae5a0cafda1719a1d863f5b1e27d4d38ef5d [file] [log] [blame]
Angel Ponsf23ae0b2020-04-02 23:48:12 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Arthur Heymans2e658f82018-06-13 15:54:35 +02002
3/*
4 * input %esp: return address (not pointer to return address!)
5 * clobber the content of eax, ebx, ecx, edx, esi, edi, and ebp
6 */
7
8#include <cpu/x86/post_code.h>
9#include <cpu/x86/msr.h>
Arthur Heymans0eb9c572019-01-05 18:21:47 +010010
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)
Arthur Heymans2e658f82018-06-13 15:54:35 +020016
17#define HEADER_VER_OFFSET 0
18#define UPDATE_VER_OFFSET 4
19#define DATE_OFFSET 8
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
27
28/*
29 * The microcode header is 48 bytes wide and has the following
30 * structure:
31 * Header Version : 32bit
32 * Update Revision : 32bit
33 * Date : 32bit
34 * Processor Signature : 32bit
35 * Checksum : 32bit
36 * Loader Revision : 32bit
37 * Processor Flags : 32bit
38 * Data Size : 32bit
39 * Total Size : 32bit
40 * Reserved : 96bit
41 *
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
44 */
45
Patrick Rudolph983ea182020-11-30 13:33:41 +010046.code32
Arthur Heymans2e658f82018-06-13 15:54:35 +020047.section .text
48.global update_bsp_microcode
49
50update_bsp_microcode:
51 /* Keep return address */
52 movl %esp, %edx
53 /* find microcodes in cbfs */
54 leal microcode_name, %esi
55 movl $1f, %esp
56 jmp walkcbfs_asm
57
581:
59 /* restore return address */
60 movl %edx, %esp
61
62 cmpl $0, %eax
63 je end_microcode_update
64 movl CBFS_FILE_OFFSET(%eax), %ebx
65 bswap %ebx
66 addl %eax, %ebx
67 movl %ebx, %esi
68
69 movl CBFS_FILE_LEN(%eax), %edi
70 bswap %edi
71 addl %esi, %edi
72
73 /*
74 * Microcode revision -> %ebx
75 * Processor flags -> %ebp
76 * Current installed microcode revision -> %edx
77 */
78
Arthur Heymans2e658f82018-06-13 15:54:35 +020079 /* Processor flags
80 * rdmsr 0x17
81 * pf = 1 << ((msr.hi >> 18) & 7) */
82 movl $IA32_PLATFORM_ID, %ecx
83 rdmsr
84 shr $18, %edx
85 andl $7, %edx
86 movl $1, %eax
87 /* needs to be %cl for shl */
88 movl %edx, %ecx
89 shl %cl, %eax
90 movl %eax, %ebp
91
92 /* Fetch the current microcode revision*/
93 xorl %eax, %eax
94 xorl %edx, %edx
95 movl $IA32_BIOS_SIGN_ID, %ecx
96 wrmsr
97 movl $0x1, %eax
98 cpuid
Arthur Heymans8c70dd62019-01-05 17:20:11 +010099
100 /* Processor family+model signature=cpuid_eax(1) */
101 movl %eax, %ebx
102
Arthur Heymans2e658f82018-06-13 15:54:35 +0200103 movl $IA32_BIOS_SIGN_ID, %ecx
104 rdmsr
105
106check_microcode_entry:
107 /* Test if header revision is non zero */
108 cmpl $0, HEADER_VER_OFFSET(%esi)
109 je end_microcode_update
110
111 /* Processor family+model signature=cpuid_eax(1) */
112 cmpl PROCESSOR_SIG_OFFSET(%esi), %ebx
113 jne next_entry
114
115 /* Processor flags */
Arthur Heymans8c70dd62019-01-05 17:20:11 +0100116 test PROCESSOR_FLAG(%esi), %ebp
117 jz next_entry
Arthur Heymans2e658f82018-06-13 15:54:35 +0200118
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
123
124 /* Do actual update */
125 movl %esi, %eax
126 addl $HEADER_SIZE, %eax
127 xorl %edx, %edx
128 movl $IA32_BIOS_UPDT_TRIG, %ecx
129 wrmsr
130
131 jmp end_microcode_update
132
133next_entry:
134 movl TOTAL_OFFSET(%esi), %eax
135 cmpl $0, %eax
136 jne 1f
137 /* Newer microcode updates include a size field, whereas older
138 * containers set it at 0 and are exactly 2048 bytes long */
139 addl $2048, %esi
140 jmp check_end
1411:
142 addl %eax, %esi
143
144check_end:
145 cmpl %esi, %edi
146 ja check_microcode_entry
147
148end_microcode_update:
149 jmp *%esp
150
151microcode_name:
152 .string "cpu_microcode_blob.bin"
153
154_update_bsp_microcode_end: