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.
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.
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]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <sys/types.h>
28 #include <sys/ucode.h>
30 #include <sys/systm.h>
37 * Intel 64 and IA-32 Architectures Software Developers's Manual
38 * Chapter 9.11 Microcode Update Facilities
43 * Validates the microcode header.
44 * Returns EM_OK on success, EM_HEADER on failure.
47 ucode_header_validate_intel(ucode_header_intel_t
*uhp
)
49 uint32_t header_size
, body_size
, total_size
;
55 * The only header version number supported is 1.
57 if (uhp
->uh_header_ver
!= 0x1)
60 header_size
= UCODE_HEADER_SIZE_INTEL
;
61 total_size
= UCODE_TOTAL_SIZE_INTEL(uhp
->uh_total_size
);
62 body_size
= UCODE_BODY_SIZE_INTEL(uhp
->uh_body_size
);
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
70 if ((body_size
% sizeof (int)) ||
71 (total_size
< (header_size
+ body_size
)) ||
72 (total_size
% UCODE_KB(1)))
77 * Sanity check to avoid reading bogus files
79 if (total_size
< UCODE_MIN_SIZE
|| total_size
> UCODE_MAX_SIZE
)
83 * If there is extended signature table, total_size is the sum of
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.
90 if (total_size
> (header_size
+ body_size
)) {
91 if ((total_size
- body_size
- header_size
-
92 UCODE_EXT_TABLE_SIZE_INTEL
) % UCODE_EXT_SIG_SIZE_INTEL
) {
105 ucode_checksum_intel(uint32_t sum
, uint32_t size
, uint8_t *code
)
108 uint32_t *lcode
= (uint32_t *)(intptr_t)code
;
118 ucode_validate_amd(uint8_t *ucodep
, int size
)
120 /* LINTED: pointer alignment */
121 uint32_t *ptr
= (uint32_t *)ucodep
;
124 if (ucodep
== NULL
|| size
<= 0)
125 return (EM_INVALIDARG
);
127 /* Magic Number: "AMD\0" */
129 if (*ptr
++ != 0x00414d44)
130 return (EM_FILEFORMAT
);
132 /* equivalence table */
135 return (EM_FILEFORMAT
);
138 if (((count
= *ptr
++) > size
) || (count
% 16))
139 return (EM_FILEFORMAT
);
141 /* LINTED: pointer alignment */
142 ptr
= (uint32_t *)(((uint8_t *)ptr
) + count
);
146 /* microcode patch */
149 return (EM_FILEFORMAT
);
152 if (((count
= *ptr
++) > size
))
153 return (EM_FILEFORMAT
);
155 /* LINTED: pointer alignment */
156 ptr
= (uint32_t *)(((uint8_t *)ptr
) + count
);
161 return (EM_FILEFORMAT
);
167 ucode_validate_intel(uint8_t *ucodep
, int size
)
169 uint32_t header_size
= UCODE_HEADER_SIZE_INTEL
;
172 if (ucodep
== NULL
|| size
<= 0)
173 return (EM_INVALIDARG
);
175 for (remaining
= size
; remaining
> 0; ) {
176 uint32_t total_size
, body_size
, ext_size
;
177 ucode_header_intel_t
*uhp
;
178 uint8_t *curbuf
= &ucodep
[size
- remaining
];
181 uhp
= (ucode_header_intel_t
*)(intptr_t)curbuf
;
183 if ((rc
= ucode_header_validate_intel(uhp
)) != EM_OK
)
186 total_size
= UCODE_TOTAL_SIZE_INTEL(uhp
->uh_total_size
);
188 if (ucode_checksum_intel(0, total_size
, curbuf
))
189 return (EM_CHECKSUM
);
191 body_size
= UCODE_BODY_SIZE_INTEL(uhp
->uh_body_size
);
192 ext_size
= total_size
- (header_size
+ body_size
);
197 if (ucode_checksum_intel(0, ext_size
,
198 &curbuf
[header_size
+ body_size
])) {
199 return (EM_CHECKSUM
);
202 ext_size
-= UCODE_EXT_TABLE_SIZE_INTEL
;
203 for (i
= 0; i
< ext_size
/ UCODE_EXT_SIG_SIZE_INTEL
;
205 if (ucode_checksum_intel(0,
206 UCODE_EXT_SIG_SIZE_INTEL
,
207 &curbuf
[total_size
- ext_size
+
208 i
* UCODE_EXT_SIG_SIZE_INTEL
])) {
210 return (EM_CHECKSUM
);
215 remaining
-= total_size
;