0001
0002
0003
0004 #include <linux/firmware.h>
0005 #include <asm/cpu.h>
0006 #include <linux/slab.h>
0007 #include <asm/microcode_intel.h>
0008
0009 #include "ifs.h"
0010
0011 struct ifs_header {
0012 u32 header_ver;
0013 u32 blob_revision;
0014 u32 date;
0015 u32 processor_sig;
0016 u32 check_sum;
0017 u32 loader_rev;
0018 u32 processor_flags;
0019 u32 metadata_size;
0020 u32 total_size;
0021 u32 fusa_info;
0022 u64 reserved;
0023 };
0024
0025 #define IFS_HEADER_SIZE (sizeof(struct ifs_header))
0026 static struct ifs_header *ifs_header_ptr;
0027 static u64 ifs_hash_ptr;
0028 static u64 ifs_test_image_ptr;
0029 static DECLARE_COMPLETION(ifs_done);
0030
0031 static const char * const scan_hash_status[] = {
0032 [0] = "No error reported",
0033 [1] = "Attempt to copy scan hashes when copy already in progress",
0034 [2] = "Secure Memory not set up correctly",
0035 [3] = "FuSaInfo.ProgramID does not match or ff-mm-ss does not match",
0036 [4] = "Reserved",
0037 [5] = "Integrity check failed",
0038 [6] = "Scan reload or test is in progress"
0039 };
0040
0041 static const char * const scan_authentication_status[] = {
0042 [0] = "No error reported",
0043 [1] = "Attempt to authenticate a chunk which is already marked as authentic",
0044 [2] = "Chunk authentication error. The hash of chunk did not match expected value"
0045 };
0046
0047
0048
0049
0050
0051
0052
0053 static void copy_hashes_authenticate_chunks(struct work_struct *work)
0054 {
0055 struct ifs_work *local_work = container_of(work, struct ifs_work, w);
0056 union ifs_scan_hashes_status hashes_status;
0057 union ifs_chunks_auth_status chunk_status;
0058 struct device *dev = local_work->dev;
0059 int i, num_chunks, chunk_size;
0060 struct ifs_data *ifsd;
0061 u64 linear_addr, base;
0062 u32 err_code;
0063
0064 ifsd = ifs_get_data(dev);
0065
0066 wrmsrl(MSR_COPY_SCAN_HASHES, ifs_hash_ptr);
0067 rdmsrl(MSR_SCAN_HASHES_STATUS, hashes_status.data);
0068
0069
0070 num_chunks = hashes_status.num_chunks;
0071 chunk_size = hashes_status.chunk_size * 1024;
0072 err_code = hashes_status.error_code;
0073
0074 if (!hashes_status.valid) {
0075 ifsd->loading_error = true;
0076 if (err_code >= ARRAY_SIZE(scan_hash_status)) {
0077 dev_err(dev, "invalid error code 0x%x for hash copy\n", err_code);
0078 goto done;
0079 }
0080 dev_err(dev, "Hash copy error : %s", scan_hash_status[err_code]);
0081 goto done;
0082 }
0083
0084
0085 base = ifs_test_image_ptr;
0086
0087
0088 for (i = 0; i < num_chunks; i++) {
0089 linear_addr = base + i * chunk_size;
0090 linear_addr |= i;
0091
0092 wrmsrl(MSR_AUTHENTICATE_AND_COPY_CHUNK, linear_addr);
0093 rdmsrl(MSR_CHUNKS_AUTHENTICATION_STATUS, chunk_status.data);
0094
0095 ifsd->valid_chunks = chunk_status.valid_chunks;
0096 err_code = chunk_status.error_code;
0097
0098 if (err_code) {
0099 ifsd->loading_error = true;
0100 if (err_code >= ARRAY_SIZE(scan_authentication_status)) {
0101 dev_err(dev,
0102 "invalid error code 0x%x for authentication\n", err_code);
0103 goto done;
0104 }
0105 dev_err(dev, "Chunk authentication error %s\n",
0106 scan_authentication_status[err_code]);
0107 goto done;
0108 }
0109 }
0110 done:
0111 complete(&ifs_done);
0112 }
0113
0114
0115
0116
0117
0118
0119 static int scan_chunks_sanity_check(struct device *dev)
0120 {
0121 int metadata_size, curr_pkg, cpu, ret = -ENOMEM;
0122 struct ifs_data *ifsd = ifs_get_data(dev);
0123 bool *package_authenticated;
0124 struct ifs_work local_work;
0125 char *test_ptr;
0126
0127 package_authenticated = kcalloc(topology_max_packages(), sizeof(bool), GFP_KERNEL);
0128 if (!package_authenticated)
0129 return ret;
0130
0131 metadata_size = ifs_header_ptr->metadata_size;
0132
0133
0134 if (metadata_size == 0)
0135 metadata_size = 2000;
0136
0137
0138 if ((metadata_size + IFS_HEADER_SIZE) % 256) {
0139 dev_err(dev, "Scan pattern offset within the binary is not 256 byte aligned\n");
0140 return -EINVAL;
0141 }
0142
0143 test_ptr = (char *)ifs_header_ptr + IFS_HEADER_SIZE + metadata_size;
0144 ifsd->loading_error = false;
0145
0146 ifs_test_image_ptr = (u64)test_ptr;
0147 ifsd->loaded_version = ifs_header_ptr->blob_revision;
0148
0149
0150 cpus_read_lock();
0151 for_each_online_cpu(cpu) {
0152 curr_pkg = topology_physical_package_id(cpu);
0153 if (package_authenticated[curr_pkg])
0154 continue;
0155 reinit_completion(&ifs_done);
0156 local_work.dev = dev;
0157 INIT_WORK(&local_work.w, copy_hashes_authenticate_chunks);
0158 schedule_work_on(cpu, &local_work.w);
0159 wait_for_completion(&ifs_done);
0160 if (ifsd->loading_error)
0161 goto out;
0162 package_authenticated[curr_pkg] = 1;
0163 }
0164 ret = 0;
0165 out:
0166 cpus_read_unlock();
0167 kfree(package_authenticated);
0168
0169 return ret;
0170 }
0171
0172 static int ifs_sanity_check(struct device *dev,
0173 const struct microcode_header_intel *mc_header)
0174 {
0175 unsigned long total_size, data_size;
0176 u32 sum, *mc;
0177
0178 total_size = get_totalsize(mc_header);
0179 data_size = get_datasize(mc_header);
0180
0181 if ((data_size + MC_HEADER_SIZE > total_size) || (total_size % sizeof(u32))) {
0182 dev_err(dev, "bad ifs data file size.\n");
0183 return -EINVAL;
0184 }
0185
0186 if (mc_header->ldrver != 1 || mc_header->hdrver != 1) {
0187 dev_err(dev, "invalid/unknown ifs update format.\n");
0188 return -EINVAL;
0189 }
0190
0191 mc = (u32 *)mc_header;
0192 sum = 0;
0193 for (int i = 0; i < total_size / sizeof(u32); i++)
0194 sum += mc[i];
0195
0196 if (sum) {
0197 dev_err(dev, "bad ifs data checksum, aborting.\n");
0198 return -EINVAL;
0199 }
0200
0201 return 0;
0202 }
0203
0204 static bool find_ifs_matching_signature(struct device *dev, struct ucode_cpu_info *uci,
0205 const struct microcode_header_intel *shdr)
0206 {
0207 unsigned int mc_size;
0208
0209 mc_size = get_totalsize(shdr);
0210
0211 if (!mc_size || ifs_sanity_check(dev, shdr) < 0) {
0212 dev_err(dev, "ifs sanity check failure\n");
0213 return false;
0214 }
0215
0216 if (!intel_cpu_signatures_match(uci->cpu_sig.sig, uci->cpu_sig.pf, shdr->sig, shdr->pf)) {
0217 dev_err(dev, "ifs signature, pf not matching\n");
0218 return false;
0219 }
0220
0221 return true;
0222 }
0223
0224 static bool ifs_image_sanity_check(struct device *dev, const struct microcode_header_intel *data)
0225 {
0226 struct ucode_cpu_info uci;
0227
0228 intel_cpu_collect_info(&uci);
0229
0230 return find_ifs_matching_signature(dev, &uci, data);
0231 }
0232
0233
0234
0235
0236
0237 void ifs_load_firmware(struct device *dev)
0238 {
0239 struct ifs_data *ifsd = ifs_get_data(dev);
0240 const struct firmware *fw;
0241 char scan_path[32];
0242 int ret;
0243
0244 snprintf(scan_path, sizeof(scan_path), "intel/ifs/%02x-%02x-%02x.scan",
0245 boot_cpu_data.x86, boot_cpu_data.x86_model, boot_cpu_data.x86_stepping);
0246
0247 ret = request_firmware_direct(&fw, scan_path, dev);
0248 if (ret) {
0249 dev_err(dev, "ifs file %s load failed\n", scan_path);
0250 goto done;
0251 }
0252
0253 if (!ifs_image_sanity_check(dev, (struct microcode_header_intel *)fw->data)) {
0254 dev_err(dev, "ifs header sanity check failed\n");
0255 goto release;
0256 }
0257
0258 ifs_header_ptr = (struct ifs_header *)fw->data;
0259 ifs_hash_ptr = (u64)(ifs_header_ptr + 1);
0260
0261 ret = scan_chunks_sanity_check(dev);
0262 release:
0263 release_firmware(fw);
0264 done:
0265 ifsd->loaded = (ret == 0);
0266 }