1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright(c) 2022 Intel Corporation. */
4 #include <linux/firmware.h>
5 #include <linux/sizes.h>
7 #include <asm/microcode.h>
11 #define IFS_CHUNK_ALIGNMENT 256
14 u32 meta_type
; // metadata type
15 u32 meta_size
; // size of this entire struct including hdrs.
16 u32 test_type
; // IFS test type
17 u32 fusa_info
; // Fusa info
18 u32 total_images
; // Total number of images
19 u32 current_image
; // Current Image #
20 u32 total_chunks
; // Total number of chunks in this image
21 u32 starting_chunk
; // Starting chunk number in this image
22 u32 size_per_chunk
; // size of each chunk
23 u32 chunks_per_stride
; // number of chunks in a stride
25 u8 padding
[IFS_CHUNK_ALIGNMENT
];
28 #define IFS_HEADER_SIZE (sizeof(struct microcode_header_intel))
29 #define META_TYPE_IFS 1
30 #define INVALIDATE_STRIDE 0x1UL
31 #define IFS_GEN_STRIDE_AWARE 2
32 #define AUTH_INTERRUPTED_ERROR 5
33 #define IFS_AUTH_RETRY_CT 10
35 static struct microcode_header_intel
*ifs_header_ptr
; /* pointer to the ifs image header */
36 static u64 ifs_hash_ptr
; /* Address of ifs metadata (hash) */
37 static u64 ifs_test_image_ptr
; /* 256B aligned address of test pattern */
38 static DECLARE_COMPLETION(ifs_done
);
40 static const char * const scan_hash_status
[] = {
41 [0] = "No error reported",
42 [1] = "Attempt to copy scan hashes when copy already in progress",
43 [2] = "Secure Memory not set up correctly",
44 [3] = "FuSaInfo.ProgramID does not match or ff-mm-ss does not match",
46 [5] = "Integrity check failed",
47 [6] = "Scan reload or test is in progress"
50 static const char * const scan_authentication_status
[] = {
51 [0] = "No error reported",
52 [1] = "Attempt to authenticate a chunk which is already marked as authentic",
53 [2] = "Chunk authentication error. The hash of chunk did not match expected value",
55 [4] = "Chunk outside the current stride",
56 [5] = "Authentication flow interrupted",
59 #define MC_HEADER_META_TYPE_END (0)
61 struct metadata_header
{
63 unsigned int blk_size
;
66 static struct metadata_header
*find_meta_data(void *ucode
, unsigned int meta_type
)
68 struct microcode_header_intel
*hdr
= &((struct microcode_intel
*)ucode
)->hdr
;
69 struct metadata_header
*meta_header
;
70 unsigned long data_size
, total_meta
;
71 unsigned long meta_size
= 0;
73 data_size
= intel_microcode_get_datasize(hdr
);
74 total_meta
= hdr
->metasize
;
78 meta_header
= (ucode
+ MC_HEADER_SIZE
+ data_size
) - total_meta
;
80 while (meta_header
->type
!= MC_HEADER_META_TYPE_END
&&
81 meta_header
->blk_size
&&
82 meta_size
< total_meta
) {
83 meta_size
+= meta_header
->blk_size
;
84 if (meta_header
->type
== meta_type
)
87 meta_header
= (void *)meta_header
+ meta_header
->blk_size
;
92 static void hashcopy_err_message(struct device
*dev
, u32 err_code
)
94 if (err_code
>= ARRAY_SIZE(scan_hash_status
))
95 dev_err(dev
, "invalid error code 0x%x for hash copy\n", err_code
);
97 dev_err(dev
, "Hash copy error : %s\n", scan_hash_status
[err_code
]);
100 static void auth_err_message(struct device
*dev
, u32 err_code
)
102 if (err_code
>= ARRAY_SIZE(scan_authentication_status
))
103 dev_err(dev
, "invalid error code 0x%x for authentication\n", err_code
);
105 dev_err(dev
, "Chunk authentication error : %s\n",
106 scan_authentication_status
[err_code
]);
110 * To copy scan hashes and authenticate test chunks, the initiating cpu must point
111 * to the EDX:EAX to the test image in linear address.
112 * Run wrmsr(MSR_COPY_SCAN_HASHES) for scan hash copy and run wrmsr(MSR_AUTHENTICATE_AND_COPY_CHUNK)
113 * for scan hash copy and test chunk authentication.
115 static void copy_hashes_authenticate_chunks(struct work_struct
*work
)
117 struct ifs_work
*local_work
= container_of(work
, struct ifs_work
, w
);
118 union ifs_scan_hashes_status hashes_status
;
119 union ifs_chunks_auth_status chunk_status
;
120 struct device
*dev
= local_work
->dev
;
121 const struct ifs_test_msrs
*msrs
;
122 int i
, num_chunks
, chunk_size
;
123 struct ifs_data
*ifsd
;
124 u64 linear_addr
, base
;
127 ifsd
= ifs_get_data(dev
);
128 msrs
= ifs_get_test_msrs(dev
);
129 /* run scan hash copy */
130 wrmsrl(msrs
->copy_hashes
, ifs_hash_ptr
);
131 rdmsrl(msrs
->copy_hashes_status
, hashes_status
.data
);
133 /* enumerate the scan image information */
134 num_chunks
= hashes_status
.num_chunks
;
135 chunk_size
= hashes_status
.chunk_size
* 1024;
136 err_code
= hashes_status
.error_code
;
138 if (!hashes_status
.valid
) {
139 ifsd
->loading_error
= true;
140 hashcopy_err_message(dev
, err_code
);
144 /* base linear address to the scan data */
145 base
= ifs_test_image_ptr
;
147 /* scan data authentication and copy chunks to secured memory */
148 for (i
= 0; i
< num_chunks
; i
++) {
149 linear_addr
= base
+ i
* chunk_size
;
152 wrmsrl(msrs
->copy_chunks
, linear_addr
);
153 rdmsrl(msrs
->copy_chunks_status
, chunk_status
.data
);
155 ifsd
->valid_chunks
= chunk_status
.valid_chunks
;
156 err_code
= chunk_status
.error_code
;
159 ifsd
->loading_error
= true;
160 auth_err_message(dev
, err_code
);
168 static int get_num_chunks(int gen
, union ifs_scan_hashes_status_gen2 status
)
170 return gen
>= IFS_GEN_STRIDE_AWARE
? status
.chunks_in_stride
: status
.num_chunks
;
173 static bool need_copy_scan_hashes(struct ifs_data
*ifsd
)
175 return !ifsd
->loaded
||
176 ifsd
->generation
< IFS_GEN_STRIDE_AWARE
||
177 ifsd
->loaded_version
!= ifs_header_ptr
->rev
;
180 static int copy_hashes_authenticate_chunks_gen2(struct device
*dev
)
182 union ifs_scan_hashes_status_gen2 hashes_status
;
183 union ifs_chunks_auth_status_gen2 chunk_status
;
184 u32 err_code
, valid_chunks
, total_chunks
;
185 const struct ifs_test_msrs
*msrs
;
186 int i
, num_chunks
, chunk_size
;
187 union meta_data
*ifs_meta
;
188 int starting_chunk_nr
;
189 struct ifs_data
*ifsd
;
190 u64 linear_addr
, base
;
194 ifsd
= ifs_get_data(dev
);
195 msrs
= ifs_get_test_msrs(dev
);
197 if (need_copy_scan_hashes(ifsd
)) {
198 wrmsrl(msrs
->copy_hashes
, ifs_hash_ptr
);
199 rdmsrl(msrs
->copy_hashes_status
, hashes_status
.data
);
201 /* enumerate the scan image information */
202 chunk_size
= hashes_status
.chunk_size
* SZ_1K
;
203 err_code
= hashes_status
.error_code
;
205 num_chunks
= get_num_chunks(ifsd
->generation
, hashes_status
);
207 if (!hashes_status
.valid
) {
208 hashcopy_err_message(dev
, err_code
);
211 ifsd
->loaded_version
= ifs_header_ptr
->rev
;
212 ifsd
->chunk_size
= chunk_size
;
214 num_chunks
= ifsd
->valid_chunks
;
215 chunk_size
= ifsd
->chunk_size
;
218 if (ifsd
->generation
>= IFS_GEN_STRIDE_AWARE
) {
219 wrmsrl(msrs
->test_ctrl
, INVALIDATE_STRIDE
);
220 rdmsrl(msrs
->copy_chunks_status
, chunk_status
.data
);
221 if (chunk_status
.valid_chunks
!= 0) {
222 dev_err(dev
, "Couldn't invalidate installed stride - %d\n",
223 chunk_status
.valid_chunks
);
228 base
= ifs_test_image_ptr
;
229 ifs_meta
= (union meta_data
*)find_meta_data(ifs_header_ptr
, META_TYPE_IFS
);
230 starting_chunk_nr
= ifs_meta
->starting_chunk
;
232 /* scan data authentication and copy chunks to secured memory */
233 for (i
= 0; i
< num_chunks
; i
++) {
234 retry_count
= IFS_AUTH_RETRY_CT
;
235 linear_addr
= base
+ i
* chunk_size
;
237 chunk_table
[0] = starting_chunk_nr
+ i
;
238 chunk_table
[1] = linear_addr
;
241 wrmsrl(msrs
->copy_chunks
, (u64
)chunk_table
);
243 rdmsrl(msrs
->copy_chunks_status
, chunk_status
.data
);
244 err_code
= chunk_status
.error_code
;
245 } while (err_code
== AUTH_INTERRUPTED_ERROR
&& --retry_count
);
248 ifsd
->loading_error
= true;
249 auth_err_message(dev
, err_code
);
254 valid_chunks
= chunk_status
.valid_chunks
;
255 total_chunks
= chunk_status
.total_chunks
;
257 if (valid_chunks
!= total_chunks
) {
258 ifsd
->loading_error
= true;
259 dev_err(dev
, "Couldn't authenticate all the chunks. Authenticated %d total %d.\n",
260 valid_chunks
, total_chunks
);
263 ifsd
->valid_chunks
= valid_chunks
;
264 ifsd
->max_bundle
= chunk_status
.max_bundle
;
269 static int validate_ifs_metadata(struct device
*dev
)
271 const struct ifs_test_caps
*test
= ifs_get_test_caps(dev
);
272 struct ifs_data
*ifsd
= ifs_get_data(dev
);
273 union meta_data
*ifs_meta
;
277 snprintf(test_file
, sizeof(test_file
), "%02x-%02x-%02x-%02x.%s",
278 boot_cpu_data
.x86
, boot_cpu_data
.x86_model
,
279 boot_cpu_data
.x86_stepping
, ifsd
->cur_batch
, test
->image_suffix
);
281 ifs_meta
= (union meta_data
*)find_meta_data(ifs_header_ptr
, META_TYPE_IFS
);
283 dev_err(dev
, "IFS Metadata missing in file %s\n", test_file
);
287 ifs_test_image_ptr
= (u64
)ifs_meta
+ sizeof(union meta_data
);
289 /* Scan chunk start must be 256 byte aligned */
290 if (!IS_ALIGNED(ifs_test_image_ptr
, IFS_CHUNK_ALIGNMENT
)) {
291 dev_err(dev
, "Scan pattern is not aligned on %d bytes aligned in %s\n",
292 IFS_CHUNK_ALIGNMENT
, test_file
);
296 if (ifs_meta
->current_image
!= ifsd
->cur_batch
) {
297 dev_warn(dev
, "Mismatch between filename %s and batch metadata 0x%02x\n",
298 test_file
, ifs_meta
->current_image
);
302 if (ifs_meta
->chunks_per_stride
&&
303 (ifs_meta
->starting_chunk
% ifs_meta
->chunks_per_stride
!= 0)) {
304 dev_warn(dev
, "Starting chunk num %u not a multiple of chunks_per_stride %u\n",
305 ifs_meta
->starting_chunk
, ifs_meta
->chunks_per_stride
);
309 if (ifs_meta
->test_type
!= test
->test_num
) {
310 dev_warn(dev
, "Metadata test_type %d mismatches with device type\n",
311 ifs_meta
->test_type
);
319 * IFS requires scan chunks authenticated per each socket in the platform.
320 * Once the test chunk is authenticated, it is automatically copied to secured memory
321 * and proceed the authentication for the next chunk.
323 static int scan_chunks_sanity_check(struct device
*dev
)
325 struct ifs_data
*ifsd
= ifs_get_data(dev
);
326 struct ifs_work local_work
;
327 int curr_pkg
, cpu
, ret
;
329 memset(ifs_pkg_auth
, 0, (topology_max_packages() * sizeof(bool)));
330 ret
= validate_ifs_metadata(dev
);
334 ifsd
->loading_error
= false;
336 if (ifsd
->generation
> 0)
337 return copy_hashes_authenticate_chunks_gen2(dev
);
339 /* copy the scan hash and authenticate per package */
341 for_each_online_cpu(cpu
) {
342 curr_pkg
= topology_physical_package_id(cpu
);
343 if (ifs_pkg_auth
[curr_pkg
])
345 reinit_completion(&ifs_done
);
346 local_work
.dev
= dev
;
347 INIT_WORK_ONSTACK(&local_work
.w
, copy_hashes_authenticate_chunks
);
348 schedule_work_on(cpu
, &local_work
.w
);
349 wait_for_completion(&ifs_done
);
350 if (ifsd
->loading_error
) {
354 ifs_pkg_auth
[curr_pkg
] = 1;
357 ifsd
->loaded_version
= ifs_header_ptr
->rev
;
364 static int image_sanity_check(struct device
*dev
, const struct microcode_header_intel
*data
)
366 struct cpu_signature sig
;
368 /* Provide a specific error message when loading an older/unsupported image */
369 if (data
->hdrver
!= MC_HEADER_TYPE_IFS
) {
370 dev_err(dev
, "Header version %d not supported\n", data
->hdrver
);
374 if (intel_microcode_sanity_check((void *)data
, true, MC_HEADER_TYPE_IFS
)) {
375 dev_err(dev
, "sanity check failed\n");
379 intel_collect_cpu_info(&sig
);
381 if (!intel_find_matching_signature((void *)data
, &sig
)) {
382 dev_err(dev
, "cpu signature, processor flags not matching\n");
390 * Load ifs image. Before loading ifs module, the ifs image must be located
391 * in /lib/firmware/intel/ifs_x/ and named as family-model-stepping-02x.{testname}.
393 int ifs_load_firmware(struct device
*dev
)
395 const struct ifs_test_caps
*test
= ifs_get_test_caps(dev
);
396 struct ifs_data
*ifsd
= ifs_get_data(dev
);
397 unsigned int expected_size
;
398 const struct firmware
*fw
;
402 snprintf(scan_path
, sizeof(scan_path
), "intel/ifs_%d/%02x-%02x-%02x-%02x.%s",
403 test
->test_num
, boot_cpu_data
.x86
, boot_cpu_data
.x86_model
,
404 boot_cpu_data
.x86_stepping
, ifsd
->cur_batch
, test
->image_suffix
);
406 ret
= request_firmware_direct(&fw
, scan_path
, dev
);
408 dev_err(dev
, "ifs file %s load failed\n", scan_path
);
412 expected_size
= ((struct microcode_header_intel
*)fw
->data
)->totalsize
;
413 if (fw
->size
!= expected_size
) {
414 dev_err(dev
, "File size mismatch (expected %u, actual %zu). Corrupted IFS image.\n",
415 expected_size
, fw
->size
);
420 ret
= image_sanity_check(dev
, (struct microcode_header_intel
*)fw
->data
);
424 ifs_header_ptr
= (struct microcode_header_intel
*)fw
->data
;
425 ifs_hash_ptr
= (u64
)(ifs_header_ptr
+ 1);
427 ret
= scan_chunks_sanity_check(dev
);
429 dev_err(dev
, "Load failure for batch: %02x\n", ifsd
->cur_batch
);
432 release_firmware(fw
);
434 ifsd
->loaded
= (ret
== 0);