1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright(c) 2022 Intel Corporation. */
4 #include <linux/firmware.h>
6 #include <linux/slab.h>
7 #include <asm/microcode_intel.h>
25 #define IFS_HEADER_SIZE (sizeof(struct ifs_header))
26 static struct ifs_header *ifs_header_ptr; /* pointer to the ifs image header */
27 static u64 ifs_hash_ptr; /* Address of ifs metadata (hash) */
28 static u64 ifs_test_image_ptr; /* 256B aligned address of test pattern */
29 static DECLARE_COMPLETION(ifs_done);
31 static const char * const scan_hash_status[] = {
32 [0] = "No error reported",
33 [1] = "Attempt to copy scan hashes when copy already in progress",
34 [2] = "Secure Memory not set up correctly",
35 [3] = "FuSaInfo.ProgramID does not match or ff-mm-ss does not match",
37 [5] = "Integrity check failed",
38 [6] = "Scan reload or test is in progress"
41 static const char * const scan_authentication_status[] = {
42 [0] = "No error reported",
43 [1] = "Attempt to authenticate a chunk which is already marked as authentic",
44 [2] = "Chunk authentication error. The hash of chunk did not match expected value"
48 * To copy scan hashes and authenticate test chunks, the initiating cpu must point
49 * to the EDX:EAX to the test image in linear address.
50 * Run wrmsr(MSR_COPY_SCAN_HASHES) for scan hash copy and run wrmsr(MSR_AUTHENTICATE_AND_COPY_CHUNK)
51 * for scan hash copy and test chunk authentication.
53 static void copy_hashes_authenticate_chunks(struct work_struct *work)
55 struct ifs_work *local_work = container_of(work, struct ifs_work, w);
56 union ifs_scan_hashes_status hashes_status;
57 union ifs_chunks_auth_status chunk_status;
58 struct device *dev = local_work->dev;
59 int i, num_chunks, chunk_size;
60 struct ifs_data *ifsd;
61 u64 linear_addr, base;
64 ifsd = ifs_get_data(dev);
65 /* run scan hash copy */
66 wrmsrl(MSR_COPY_SCAN_HASHES, ifs_hash_ptr);
67 rdmsrl(MSR_SCAN_HASHES_STATUS, hashes_status.data);
69 /* enumerate the scan image information */
70 num_chunks = hashes_status.num_chunks;
71 chunk_size = hashes_status.chunk_size * 1024;
72 err_code = hashes_status.error_code;
74 if (!hashes_status.valid) {
75 ifsd->loading_error = true;
76 if (err_code >= ARRAY_SIZE(scan_hash_status)) {
77 dev_err(dev, "invalid error code 0x%x for hash copy\n", err_code);
80 dev_err(dev, "Hash copy error : %s", scan_hash_status[err_code]);
84 /* base linear address to the scan data */
85 base = ifs_test_image_ptr;
87 /* scan data authentication and copy chunks to secured memory */
88 for (i = 0; i < num_chunks; i++) {
89 linear_addr = base + i * chunk_size;
92 wrmsrl(MSR_AUTHENTICATE_AND_COPY_CHUNK, linear_addr);
93 rdmsrl(MSR_CHUNKS_AUTHENTICATION_STATUS, chunk_status.data);
95 ifsd->valid_chunks = chunk_status.valid_chunks;
96 err_code = chunk_status.error_code;
99 ifsd->loading_error = true;
100 if (err_code >= ARRAY_SIZE(scan_authentication_status)) {
102 "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]);
115 * IFS requires scan chunks authenticated per each socket in the platform.
116 * Once the test chunk is authenticated, it is automatically copied to secured memory
117 * and proceed the authentication for the next chunk.
119 static int scan_chunks_sanity_check(struct device *dev)
121 int metadata_size, curr_pkg, cpu, ret = -ENOMEM;
122 struct ifs_data *ifsd = ifs_get_data(dev);
123 bool *package_authenticated;
124 struct ifs_work local_work;
127 package_authenticated = kcalloc(topology_max_packages(), sizeof(bool), GFP_KERNEL);
128 if (!package_authenticated)
131 metadata_size = ifs_header_ptr->metadata_size;
133 /* Spec says that if the Meta Data Size = 0 then it should be treated as 2000 */
134 if (metadata_size == 0)
135 metadata_size = 2000;
137 /* Scan chunk start must be 256 byte aligned */
138 if ((metadata_size + IFS_HEADER_SIZE) % 256) {
139 dev_err(dev, "Scan pattern offset within the binary is not 256 byte aligned\n");
143 test_ptr = (char *)ifs_header_ptr + IFS_HEADER_SIZE + metadata_size;
144 ifsd->loading_error = false;
146 ifs_test_image_ptr = (u64)test_ptr;
147 ifsd->loaded_version = ifs_header_ptr->blob_revision;
149 /* copy the scan hash and authenticate per package */
151 for_each_online_cpu(cpu) {
152 curr_pkg = topology_physical_package_id(cpu);
153 if (package_authenticated[curr_pkg])
155 reinit_completion(&ifs_done);
156 local_work.dev = dev;
157 INIT_WORK(&local_work.w, copy_hashes_authenticate_chunks);
158 schedule_work_on(cpu, &local_work.w);
159 wait_for_completion(&ifs_done);
160 if (ifsd->loading_error)
162 package_authenticated[curr_pkg] = 1;
167 kfree(package_authenticated);
172 static int ifs_sanity_check(struct device *dev,
173 const struct microcode_header_intel *mc_header)
175 unsigned long total_size, data_size;
178 total_size = get_totalsize(mc_header);
179 data_size = get_datasize(mc_header);
181 if ((data_size + MC_HEADER_SIZE > total_size) || (total_size % sizeof(u32))) {
182 dev_err(dev, "bad ifs data file size.\n");
186 if (mc_header->ldrver != 1 || mc_header->hdrver != 1) {
187 dev_err(dev, "invalid/unknown ifs update format.\n");
191 mc = (u32 *)mc_header;
193 for (int i = 0; i < total_size / sizeof(u32); i++)
197 dev_err(dev, "bad ifs data checksum, aborting.\n");
204 static bool find_ifs_matching_signature(struct device *dev, struct ucode_cpu_info *uci,
205 const struct microcode_header_intel *shdr)
207 unsigned int mc_size;
209 mc_size = get_totalsize(shdr);
211 if (!mc_size || ifs_sanity_check(dev, shdr) < 0) {
212 dev_err(dev, "ifs sanity check failure\n");
216 if (!intel_cpu_signatures_match(uci->cpu_sig.sig, uci->cpu_sig.pf, shdr->sig, shdr->pf)) {
217 dev_err(dev, "ifs signature, pf not matching\n");
224 static bool ifs_image_sanity_check(struct device *dev, const struct microcode_header_intel *data)
226 struct ucode_cpu_info uci;
228 intel_cpu_collect_info(&uci);
230 return find_ifs_matching_signature(dev, &uci, data);
234 * Load ifs image. Before loading ifs module, the ifs image must be located
235 * in /lib/firmware/intel/ifs and named as {family/model/stepping}.{testname}.
237 void ifs_load_firmware(struct device *dev)
239 struct ifs_data *ifsd = ifs_get_data(dev);
240 const struct firmware *fw;
244 snprintf(scan_path, sizeof(scan_path), "intel/ifs/%02x-%02x-%02x.scan",
245 boot_cpu_data.x86, boot_cpu_data.x86_model, boot_cpu_data.x86_stepping);
247 ret = request_firmware_direct(&fw, scan_path, dev);
249 dev_err(dev, "ifs file %s load failed\n", scan_path);
253 if (!ifs_image_sanity_check(dev, (struct microcode_header_intel *)fw->data)) {
254 dev_err(dev, "ifs header sanity check failed\n");
258 ifs_header_ptr = (struct ifs_header *)fw->data;
259 ifs_hash_ptr = (u64)(ifs_header_ptr + 1);
261 ret = scan_chunks_sanity_check(dev);
263 release_firmware(fw);
265 ifsd->loaded = (ret == 0);