Mercurial > illumos > illumos-gate
annotate usr/src/common/ucode/ucode_utils.c @ 13650:8f838b3f28d2
2546 Support new AMD microcode format, update bundled AMD microcode patch file
Reviewed by: Gordon Ross <gordon.w.ross@gmail.com>
Reviewed by: Garrett D'Amore <garrett@damore.org>
Reviewed by: Albert Lee <trisk@nexenta.com>
Approved by: Richard Lowe <richlowe@richlowe.net>
author | Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org> |
---|---|
date | Tue, 27 Mar 2012 13:56:18 -0500 |
parents | b4a19682e632 |
children |
rev | line source |
---|---|
4581 | 1 /* |
2 * CDDL HEADER START | |
3 * | |
4 * The contents of this file are subject to the terms of the | |
5 * Common Development and Distribution License (the "License"). | |
6 * You may not use this file except in compliance with the License. | |
7 * | |
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE | |
9 * or http://www.opensolaris.org/os/licensing. | |
10 * See the License for the specific language governing permissions | |
11 * and limitations under the License. | |
12 * | |
13 * When distributing Covered Code, include this CDDL HEADER in each | |
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. | |
15 * If applicable, add the following below this CDDL HEADER, with the | |
16 * fields enclosed by brackets "[]" replaced with your own identifying | |
17 * information: Portions Copyright [yyyy] [name of copyright owner] | |
18 * | |
19 * CDDL HEADER END | |
20 */ | |
21 | |
22 /* | |
7605
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. |
4581 | 24 * Use is subject to license terms. |
25 */ | |
26 | |
27 #include <sys/types.h> | |
28 #include <sys/ucode.h> | |
29 #ifdef _KERNEL | |
30 #include <sys/systm.h> | |
31 #else | |
32 #include <strings.h> | |
33 #endif | |
34 | |
35 /* | |
36 * Refer to | |
37 * Intel 64 and IA-32 Architectures Software Developers's Manual | |
38 * Chapter 9.11 Microcode Update Facilities | |
39 * for details. | |
40 */ | |
41 | |
42 /* | |
43 * Validates the microcode header. | |
44 * Returns EM_OK on success, EM_HEADER on failure. | |
45 */ | |
46 ucode_errno_t | |
7605
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
47 ucode_header_validate_intel(ucode_header_intel_t *uhp) |
4581 | 48 { |
49 uint32_t header_size, body_size, total_size; | |
50 | |
51 if (uhp == NULL) | |
52 return (EM_HEADER); | |
53 | |
54 /* | |
55 * The only header version number supported is 1. | |
56 */ | |
57 if (uhp->uh_header_ver != 0x1) | |
58 return (EM_HEADER); | |
59 | |
7605
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
60 header_size = UCODE_HEADER_SIZE_INTEL; |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
61 total_size = UCODE_TOTAL_SIZE_INTEL(uhp->uh_total_size); |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
62 body_size = UCODE_BODY_SIZE_INTEL(uhp->uh_body_size); |
4581 | 63 |
64 /* | |
65 * The body size field of the microcode code header specifies the size | |
66 * of the encrypted data section, its value must be a multiple of the | |
67 * size of DWORD. The total size field must be in multiples of 1K | |
68 * bytes. | |
69 */ | |
70 if ((body_size % sizeof (int)) || | |
71 (total_size < (header_size + body_size)) || | |
72 (total_size % UCODE_KB(1))) | |
73 | |
74 return (EM_HEADER); | |
75 | |
76 /* | |
77 * Sanity check to avoid reading bogus files | |
78 */ | |
79 if (total_size < UCODE_MIN_SIZE || total_size > UCODE_MAX_SIZE) | |
80 return (EM_HEADER); | |
81 | |
82 /* | |
83 * If there is extended signature table, total_size is the sum of | |
84 * header_size | |
85 * body_size | |
86 * sizeof (struct ucode_ext_table) | |
87 * n * sizeof (struct ucode_ext_sig) | |
88 * where n is indicated by uet_count in struct ucode_ext_table. | |
89 */ | |
90 if (total_size > (header_size + body_size)) { | |
91 if ((total_size - body_size - header_size - | |
7605
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
92 UCODE_EXT_TABLE_SIZE_INTEL) % UCODE_EXT_SIG_SIZE_INTEL) { |
4581 | 93 |
94 return (EM_HEADER); | |
95 } | |
96 } | |
97 | |
98 return (EM_OK); | |
99 } | |
100 | |
101 /* | |
102 * Returns checksum. | |
103 */ | |
104 uint32_t | |
7605
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
105 ucode_checksum_intel(uint32_t sum, uint32_t size, uint8_t *code) |
4581 | 106 { |
107 int i; | |
108 uint32_t *lcode = (uint32_t *)(intptr_t)code; | |
109 | |
110 i = size >> 2; | |
111 while (i--) | |
112 sum += lcode[i]; | |
113 | |
114 return (sum); | |
115 } | |
116 | |
117 ucode_errno_t | |
7605
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
118 ucode_validate_amd(uint8_t *ucodep, int size) |
4581 | 119 { |
7605
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
120 /* LINTED: pointer alignment */ |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
121 uint32_t *ptr = (uint32_t *)ucodep; |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
122 uint32_t count; |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
123 |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
124 if (ucodep == NULL || size <= 0) |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
125 return (EM_INVALIDARG); |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
126 |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
127 /* Magic Number: "AMD\0" */ |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
128 size -= 4; |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
129 if (*ptr++ != 0x00414d44) |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
130 return (EM_FILEFORMAT); |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
131 |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
132 /* equivalence table */ |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
133 size -= 4; |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
134 if (*ptr++) |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
135 return (EM_FILEFORMAT); |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
136 |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
137 size -= 4; |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
138 if (((count = *ptr++) > size) || (count % 16)) |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
139 return (EM_FILEFORMAT); |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
140 |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
141 /* LINTED: pointer alignment */ |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
142 ptr = (uint32_t *)(((uint8_t *)ptr) + count); |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
143 size -= count; |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
144 |
13650
8f838b3f28d2
2546 Support new AMD microcode format, update bundled AMD microcode patch file
Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
parents:
7605
diff
changeset
|
145 while (size > 8) { |
7605
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
146 /* microcode patch */ |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
147 size -= 4; |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
148 if (*ptr++ != 1) |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
149 return (EM_FILEFORMAT); |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
150 |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
151 size -= 4; |
13650
8f838b3f28d2
2546 Support new AMD microcode format, update bundled AMD microcode patch file
Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
parents:
7605
diff
changeset
|
152 if (((count = *ptr++) > size)) |
7605
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
153 return (EM_FILEFORMAT); |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
154 |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
155 /* LINTED: pointer alignment */ |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
156 ptr = (uint32_t *)(((uint8_t *)ptr) + count); |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
157 size -= count; |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
158 } |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
159 |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
160 if (size) |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
161 return (EM_FILEFORMAT); |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
162 |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
163 return (EM_OK); |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
164 } |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
165 |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
166 ucode_errno_t |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
167 ucode_validate_intel(uint8_t *ucodep, int size) |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
168 { |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
169 uint32_t header_size = UCODE_HEADER_SIZE_INTEL; |
4581 | 170 int remaining; |
171 | |
172 if (ucodep == NULL || size <= 0) | |
173 return (EM_INVALIDARG); | |
174 | |
175 for (remaining = size; remaining > 0; ) { | |
176 uint32_t total_size, body_size, ext_size; | |
7605
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
177 ucode_header_intel_t *uhp; |
4581 | 178 uint8_t *curbuf = &ucodep[size - remaining]; |
179 ucode_errno_t rc; | |
180 | |
7605
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
181 uhp = (ucode_header_intel_t *)(intptr_t)curbuf; |
4581 | 182 |
7605
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
183 if ((rc = ucode_header_validate_intel(uhp)) != EM_OK) |
4581 | 184 return (rc); |
185 | |
7605
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
186 total_size = UCODE_TOTAL_SIZE_INTEL(uhp->uh_total_size); |
4581 | 187 |
7605
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
188 if (ucode_checksum_intel(0, total_size, curbuf)) |
4581 | 189 return (EM_CHECKSUM); |
190 | |
7605
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
191 body_size = UCODE_BODY_SIZE_INTEL(uhp->uh_body_size); |
4581 | 192 ext_size = total_size - (header_size + body_size); |
193 | |
194 if (ext_size > 0) { | |
195 uint32_t i; | |
196 | |
7605
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
197 if (ucode_checksum_intel(0, ext_size, |
4581 | 198 &curbuf[header_size + body_size])) { |
199 return (EM_CHECKSUM); | |
200 } | |
201 | |
7605
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
202 ext_size -= UCODE_EXT_TABLE_SIZE_INTEL; |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
203 for (i = 0; i < ext_size / UCODE_EXT_SIG_SIZE_INTEL; |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
204 i++) { |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
205 if (ucode_checksum_intel(0, |
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
206 UCODE_EXT_SIG_SIZE_INTEL, |
4581 | 207 &curbuf[total_size - ext_size + |
7605
b4a19682e632
6747590 microcode update support for AMD
Mark Johnson <Mark.Johnson@Sun.COM>
parents:
4581
diff
changeset
|
208 i * UCODE_EXT_SIG_SIZE_INTEL])) { |
4581 | 209 |
210 return (EM_CHECKSUM); | |
211 } | |
212 } | |
213 } | |
214 | |
215 remaining -= total_size; | |
216 } | |
217 return (EM_OK); | |
218 } |