Message ID | 20220419163859.2228874-7-tony.luck@intel.com (mailing list archive) |
---|---|
State | Superseded, archived |
Headers | show |
Series | Introduce In Field Scan driver | expand |
On Tue, Apr 19, 2022 at 09:38:54AM -0700, Tony Luck wrote: > From: Jithu Joseph <jithu.joseph@intel.com> > > IFS image is designed specifically for a given family, model and > stepping of the processor. Like Intel microcode header, the IFS image > has the Processor Signature, Checksum and Processor Flags that must be > matched with the information returned by the CPUID. > > Reviewed-by: Dan Williams <dan.j.williams@intel.com> > Signed-off-by: Jithu Joseph <jithu.joseph@intel.com> > Co-developed-by: Tony Luck <tony.luck@intel.com> > Signed-off-by: Tony Luck <tony.luck@intel.com> > --- > drivers/platform/x86/intel/ifs/load.c | 69 +++++++++++++++++++++++++++ > 1 file changed, 69 insertions(+) > > diff --git a/drivers/platform/x86/intel/ifs/load.c b/drivers/platform/x86/intel/ifs/load.c > index fa6c64707a73..b05d9055c391 100644 > --- a/drivers/platform/x86/intel/ifs/load.c > +++ b/drivers/platform/x86/intel/ifs/load.c > @@ -3,9 +3,73 @@ > > #include <linux/firmware.h> > #include <linux/platform_device.h> > +#include <asm/cpu.h> > +#include <asm/microcode_intel.h> > > static const char *ifs_path = "intel/ifs/"; > > +static int ifs_sanity_check(struct device *dev, void *mc) > +{ > + struct microcode_header_intel *mc_header = mc; > + unsigned long total_size, data_size; > + u32 sum, i; > + > + total_size = get_totalsize(mc_header); > + data_size = get_datasize(mc_header); > + > + if ((data_size + MC_HEADER_SIZE > total_size) || (total_size % sizeof(u32))) { > + dev_err(dev, "bad ifs data file size.\n"); > + return -EINVAL; > + } > + > + if (mc_header->ldrver != 1 || mc_header->hdrver != 1) { > + dev_err(dev, "invalid/unknown ifs update format.\n"); > + return -EINVAL; > + } > + > + sum = 0; > + i = total_size / sizeof(u32); > + while (i--) > + sum += ((u32 *)mc)[i]; > + > + if (sum) { > + dev_err(dev, "bad ifs data checksum, aborting.\n"); > + return -EINVAL; > + } > + > + return 0; > +} > + > +static bool find_ifs_matching_signature(struct device *dev, struct ucode_cpu_info *uci, void *mc) > +{ > + struct microcode_header_intel *shdr; > + unsigned int mc_size; > + > + shdr = (struct microcode_header_intel *)mc; > + mc_size = get_totalsize(shdr); > + > + if (!mc_size || ifs_sanity_check(dev, shdr) < 0) { > + dev_err(dev, "ifs sanity check failure\n"); > + return false; > + } > + > + if (!intel_cpu_signatures_match(uci->cpu_sig.sig, uci->cpu_sig.pf, shdr->sig, shdr->pf)) { > + dev_err(dev, "ifs signature, pf not matching\n"); > + return false; > + } > + > + return true; > +} > + > +static bool ifs_image_sanity_check(struct device *dev, void *data) u8 *data? > +{ > + struct ucode_cpu_info uci; > + > + intel_cpu_collect_info_early(&uci); > + > + return find_ifs_matching_signature(dev, &uci, data); > +} > + > /* > * Load ifs image. Before loading ifs module, the ifs image must be located > * in /lib/firmware/intel/ifs and named as {family/model/stepping}.{testname}. > @@ -25,6 +89,11 @@ int load_ifs_binary(struct device *dev) > return ret; > } > > + if (!ifs_image_sanity_check(dev, (void *)fw->data)) { It's not a void pointer, it's a pointer to u8. Why cast it away? thanks, greg k-h
diff --git a/drivers/platform/x86/intel/ifs/load.c b/drivers/platform/x86/intel/ifs/load.c index fa6c64707a73..b05d9055c391 100644 --- a/drivers/platform/x86/intel/ifs/load.c +++ b/drivers/platform/x86/intel/ifs/load.c @@ -3,9 +3,73 @@ #include <linux/firmware.h> #include <linux/platform_device.h> +#include <asm/cpu.h> +#include <asm/microcode_intel.h> static const char *ifs_path = "intel/ifs/"; +static int ifs_sanity_check(struct device *dev, void *mc) +{ + struct microcode_header_intel *mc_header = mc; + unsigned long total_size, data_size; + u32 sum, i; + + total_size = get_totalsize(mc_header); + data_size = get_datasize(mc_header); + + if ((data_size + MC_HEADER_SIZE > total_size) || (total_size % sizeof(u32))) { + dev_err(dev, "bad ifs data file size.\n"); + return -EINVAL; + } + + if (mc_header->ldrver != 1 || mc_header->hdrver != 1) { + dev_err(dev, "invalid/unknown ifs update format.\n"); + return -EINVAL; + } + + sum = 0; + i = total_size / sizeof(u32); + while (i--) + sum += ((u32 *)mc)[i]; + + if (sum) { + dev_err(dev, "bad ifs data checksum, aborting.\n"); + return -EINVAL; + } + + return 0; +} + +static bool find_ifs_matching_signature(struct device *dev, struct ucode_cpu_info *uci, void *mc) +{ + struct microcode_header_intel *shdr; + unsigned int mc_size; + + shdr = (struct microcode_header_intel *)mc; + mc_size = get_totalsize(shdr); + + if (!mc_size || ifs_sanity_check(dev, shdr) < 0) { + dev_err(dev, "ifs sanity check failure\n"); + return false; + } + + if (!intel_cpu_signatures_match(uci->cpu_sig.sig, uci->cpu_sig.pf, shdr->sig, shdr->pf)) { + dev_err(dev, "ifs signature, pf not matching\n"); + return false; + } + + return true; +} + +static bool ifs_image_sanity_check(struct device *dev, void *data) +{ + struct ucode_cpu_info uci; + + intel_cpu_collect_info_early(&uci); + + return find_ifs_matching_signature(dev, &uci, data); +} + /* * Load ifs image. Before loading ifs module, the ifs image must be located * in /lib/firmware/intel/ifs and named as {family/model/stepping}.{testname}. @@ -25,6 +89,11 @@ int load_ifs_binary(struct device *dev) return ret; } + if (!ifs_image_sanity_check(dev, (void *)fw->data)) { + dev_err(dev, "ifs header sanity check failed\n"); + ret = -ENOENT; + } + release_firmware(fw); return ret;