port the amd64 code for loading intel microcode on boot to i386
authorjsg <jsg@openbsd.org>
Thu, 23 Aug 2018 14:47:52 +0000 (14:47 +0000)
committerjsg <jsg@openbsd.org>
Thu, 23 Aug 2018 14:47:52 +0000 (14:47 +0000)
ok deraadt@ mlarkin@

13 files changed:
sys/arch/i386/conf/files.i386
sys/arch/i386/i386/acpi_machdep.c
sys/arch/i386/i386/bios.c
sys/arch/i386/i386/cpu.c
sys/arch/i386/i386/machdep.c
sys/arch/i386/i386/ucode.c [new file with mode: 0644]
sys/arch/i386/include/biosvar.h
sys/arch/i386/include/cpufunc.h
sys/arch/i386/include/specialreg.h
sys/arch/i386/stand/boot/conf.c
sys/arch/i386/stand/cdboot/conf.c
sys/arch/i386/stand/libsa/exec_i386.c
sys/arch/i386/stand/pxeboot/conf.c

index ccc0b12..e443238 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: files.i386,v 1.242 2018/08/21 18:06:12 anton Exp $
+#      $OpenBSD: files.i386,v 1.243 2018/08/23 14:47:52 jsg Exp $
 #
 # new style config file for i386 architecture
 #
@@ -26,6 +26,7 @@ file  arch/i386/i386/via.c
 file   arch/i386/i386/locore.s
 file   arch/i386/i386/amd64errata.c    !small_kernel
 file   arch/i386/i386/longrun.c        !small_kernel
+file   arch/i386/i386/ucode.c          !small_kernel
 file   arch/i386/i386/mem.c
 file   arch/i386/i386/i686_mem.c       mtrr
 file   arch/i386/i386/k6_mem.c         mtrr
index 163f463..bdc97fa 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: acpi_machdep.c,v 1.69 2018/08/19 08:23:47 kettenis Exp $      */
+/*     $OpenBSD: acpi_machdep.c,v 1.70 2018/08/23 14:47:52 jsg Exp $   */
 /*
  * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
  *
@@ -445,6 +445,7 @@ acpi_resume_cpu(struct acpi_softc *sc)
        npxinit(&cpu_info_primary);
 
        cpu_init(&cpu_info_primary);
+       cpu_ucode_apply(&cpu_info_primary);
        
        /* Re-initialise memory range handling on BSP */
        if (mem_range_softc.mr_op != NULL)
index a6c3752..58e7ce4 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: bios.c,v 1.118 2018/04/28 15:44:59 jasper Exp $       */
+/*     $OpenBSD: bios.c,v 1.119 2018/08/23 14:47:52 jsg Exp $  */
 
 /*
  * Copyright (c) 1997-2001 Michael Shalayeff
@@ -122,6 +122,7 @@ bios_bootmac_t      *bios_bootmac;
 #ifdef DDB
 extern int     db_console;
 #endif
+bios_ucode_t   *bios_ucode;
 
 void           smbios_info(char*);
 
@@ -608,6 +609,10 @@ bios_getopt(void)
                        explicit_bzero(bios_bootsr, sizeof(bios_bootsr_t));
                        break;
 
+               case BOOTARG_UCODE:
+                       bios_ucode = (bios_ucode_t *)q->ba_arg;
+                       break;
+
                default:
 #ifdef BIOS_DEBUG
                        printf(" unsupported arg (%d) %p", q->ba_type,
index 5496456..ded91fc 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cpu.c,v 1.94 2018/07/30 14:19:12 kettenis Exp $       */
+/*     $OpenBSD: cpu.c,v 1.95 2018/08/23 14:47:52 jsg Exp $    */
 /* $NetBSD: cpu.c,v 1.1.2.7 2000/06/26 02:04:05 sommerfeld Exp $ */
 
 /*-
@@ -317,6 +317,9 @@ cpu_attach(struct device *parent, struct device *self, void *aux)
        case CPU_ROLE_SP:
                printf("(uniprocessor)\n");
                ci->ci_flags |= CPUF_PRESENT | CPUF_SP | CPUF_PRIMARY;
+#ifndef SMALL_KERNEL
+               cpu_ucode_apply(ci);
+#endif
                identifycpu(ci);
 #ifdef MTRR
                mem_range_attach();
@@ -328,6 +331,9 @@ cpu_attach(struct device *parent, struct device *self, void *aux)
        case CPU_ROLE_BP:
                printf("apid %d (boot processor)\n", caa->cpu_apicid);
                ci->ci_flags |= CPUF_PRESENT | CPUF_BSP | CPUF_PRIMARY;
+#ifndef SMALL_KERNEL
+               cpu_ucode_apply(ci);
+#endif
                identifycpu(ci);
 #ifdef MTRR
                mem_range_attach();
@@ -356,6 +362,9 @@ cpu_attach(struct device *parent, struct device *self, void *aux)
 #ifdef MULTIPROCESSOR
                gdt_alloc_cpu(ci);
                ci->ci_flags |= CPUF_PRESENT | CPUF_AP;
+#ifndef SMALL_KERNEL
+               cpu_ucode_apply(ci);
+#endif
                identifycpu(ci);
                sched_init_cpu(ci);
                ci->ci_next = cpu_info_list->ci_next;
index 57dfb38..b3c2069 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: machdep.c,v 1.625 2018/08/21 12:44:13 jsg Exp $       */
+/*     $OpenBSD: machdep.c,v 1.626 2018/08/23 14:47:52 jsg Exp $       */
 /*     $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $    */
 
 /*-
@@ -422,6 +422,10 @@ cpu_startup(void)
        }
        ioport_malloc_safe = 1;
 
+#ifndef SMALL_KERNEL
+       cpu_ucode_setup();
+#endif
+
        /* enter the IDT and trampoline code in the u-k maps */
        enter_shared_special_pages();
 
diff --git a/sys/arch/i386/i386/ucode.c b/sys/arch/i386/i386/ucode.c
new file mode 100644 (file)
index 0000000..a5c10da
--- /dev/null
@@ -0,0 +1,328 @@
+/*     $OpenBSD: ucode.c,v 1.1 2018/08/23 14:47:52 jsg Exp $   */
+/*
+ * Copyright (c) 2018 Stefan Fritsch <fritsch@genua.de>
+ * Copyright (c) 2018 Patrick Wildt <patrick@blueri.se>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/mutex.h>
+#include <sys/malloc.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/specialreg.h>
+#include <machine/biosvar.h>
+
+/* #define UCODE_DEBUG */
+#ifdef UCODE_DEBUG
+#define DPRINTF(x)     do { if (cpu_ucode_debug > 0) printf x; } while (0)
+#define DPRINTFN(n, x) do { if (cpu_ucode_debug >= (n)) printf x; } while (0)
+int cpu_ucode_debug = 1;
+#else
+#define DPRINTF(x)     do { ; } while (0)
+#define DPRINTFN(n, x) do { ; } while (0)
+#endif
+
+struct intel_ucode_header {
+       uint32_t        header_version;
+       uint32_t        update_revision;
+       uint32_t        date;
+       uint32_t        processor_sig;
+       uint32_t        checksum;
+       uint32_t        loader_rev;
+       uint32_t        processor_flags;
+       uint32_t        data_size;
+       uint32_t        total_size;
+       uint32_t        reserved[3];
+};
+
+struct intel_ucode_ext_sig_header {
+       uint32_t        ext_sig_count;
+       uint32_t        checksum;
+       uint32_t        reserved[3];
+};
+
+struct intel_ucode_ext_sig {
+       uint32_t        processor_sig;
+       uint32_t        processor_flags;
+       uint32_t        checksum;
+};
+
+#define INTEL_UCODE_DEFAULT_DATA_SIZE          2000
+
+/* Generic */
+char *  cpu_ucode_data;
+size_t  cpu_ucode_size;
+
+void    cpu_ucode_setup(void);
+void    cpu_ucode_apply(struct cpu_info *);
+
+/* Intel */
+void    cpu_ucode_intel_apply(struct cpu_info *);
+struct intel_ucode_header *
+        cpu_ucode_intel_find(char *, size_t, uint32_t);
+int     cpu_ucode_intel_verify(struct intel_ucode_header *);
+int     cpu_ucode_intel_match(struct intel_ucode_header *, uint32_t, uint32_t,
+           uint32_t);
+uint32_t cpu_ucode_intel_rev(void);
+
+struct intel_ucode_header      *cpu_ucode_intel_applied;
+struct mutex                    cpu_ucode_intel_mtx = MUTEX_INITIALIZER(IPL_HIGH);
+
+void
+cpu_ucode_setup(void)
+{
+       vaddr_t va;
+       paddr_t pa;
+       int i, npages;
+       size_t size;
+
+       if (bios_ucode == NULL)
+               return;
+
+       if (!bios_ucode->uc_addr || !bios_ucode->uc_size)
+               return;
+
+       cpu_ucode_size = bios_ucode->uc_size;
+       size = round_page(bios_ucode->uc_size);
+       npages = size / PAGE_SIZE;
+
+       va = uvm_km_valloc(kernel_map, size);
+       if (va == 0)
+               return;
+       for (i = 0; i < npages; i++) {
+               pa = bios_ucode->uc_addr + (i * PAGE_SIZE);
+               pmap_enter(pmap_kernel(), va + (i * PAGE_SIZE), pa,
+                   PROT_READ,
+                   PROT_READ | PMAP_WIRED);
+               pmap_update(pmap_kernel());
+       }
+
+       cpu_ucode_data = malloc(cpu_ucode_size, M_DEVBUF, M_WAITOK);
+
+       memcpy((void *)cpu_ucode_data, (void *)va, cpu_ucode_size);
+
+       pmap_remove(pmap_kernel(), va, va + size);
+       pmap_update(pmap_kernel());
+       uvm_km_free(kernel_map, va, size);
+}
+
+/*
+ * Called per-CPU.
+ */
+void
+cpu_ucode_apply(struct cpu_info *ci)
+{
+       if (strcmp(cpu_vendor, "GenuineIntel") == 0)
+               cpu_ucode_intel_apply(ci);
+}
+
+void
+cpu_ucode_intel_apply(struct cpu_info *ci)
+{
+       struct intel_ucode_header *update;
+       uint32_t old_rev, new_rev;
+       paddr_t data;
+
+       if (cpu_ucode_data == NULL || cpu_ucode_size == 0) {
+               DPRINTF(("%s: no microcode provided\n", __func__));
+               return;
+       }
+
+       /*
+        * Grab a mutex, because we are not allowed to run updates
+        * simultaneously on HT siblings.
+        */
+       mtx_enter(&cpu_ucode_intel_mtx);
+
+       old_rev = cpu_ucode_intel_rev();
+       update = cpu_ucode_intel_applied;
+       if (update == NULL)
+               update = cpu_ucode_intel_find(cpu_ucode_data,
+                   cpu_ucode_size, old_rev);
+       if (update == NULL) {
+               DPRINTF(("%s: no microcode update found\n", __func__));
+               goto out;
+       }
+       if (update->update_revision == old_rev) {
+               DPRINTF(("%s: microcode already up-to-date\n", __func__));
+               goto out;
+       }
+
+       /* Apply microcode. */
+       data = (paddr_t)update;
+       data += sizeof(struct intel_ucode_header);
+       wrmsr(MSR_BIOS_UPDT_TRIG, data);
+
+       new_rev = cpu_ucode_intel_rev();
+       if (new_rev != old_rev) {
+               DPRINTF(("%s: microcode updated cpu %ld rev %#x->%#x (%x)\n",
+                   __func__, ci->ci_cpuid, old_rev, new_rev, update->date));
+               if (cpu_ucode_intel_applied == NULL)
+                       cpu_ucode_intel_applied = update;
+       } else {
+               DPRINTF(("%s: microcode update failed cpu %ld rev %#x->%#x != %#x\n",
+                    __func__, ci->ci_cpuid, old_rev, update->update_revision, new_rev));
+       }
+
+out:
+       mtx_leave(&cpu_ucode_intel_mtx);
+}
+
+struct intel_ucode_header *
+cpu_ucode_intel_find(char *data, size_t left, uint32_t current)
+{
+       uint64_t platform_id = (rdmsr(MSR_PLATFORM_ID) >> 50) & 0xff;
+       uint32_t sig, dummy1, dummy2, dummy3;
+       uint32_t mask = 1UL << platform_id;
+       struct intel_ucode_header *hdr;
+       uint32_t total_size;
+       int n = 0;
+
+       CPUID(1, sig, dummy1, dummy2, dummy3);
+
+       while (left > 0) {
+               hdr = (struct intel_ucode_header *)data;
+               if (left < sizeof(struct intel_ucode_header)) {
+                       DPRINTF(("%s:%d: not enough data for header (%zd)\n",
+                           __func__, n, left));
+                       break;
+               }
+               /*
+                * Older microcode has an empty length.  In that case we
+                * have to use the default length of 2000.
+                */
+               if (hdr->data_size)
+                       total_size = hdr->total_size;
+               else
+                       total_size = INTEL_UCODE_DEFAULT_DATA_SIZE +
+                            sizeof(struct intel_ucode_header);
+               if (total_size > left) {
+                       DPRINTF(("%s:%d: size %u out of range (%zd)\n",
+                           __func__, n, total_size, left));
+                       break;
+               }
+               if (cpu_ucode_intel_verify(hdr)) {
+                       DPRINTF(("%s:%d: broken data\n", __func__, n));
+                       break;
+               }
+               if (cpu_ucode_intel_match(hdr, sig, mask, current))
+                       return hdr;
+               n++;
+               left -= total_size;
+               data += total_size;
+       }
+       DPRINTF(("%s: no update found\n", __func__));
+       return NULL;
+}
+
+int
+cpu_ucode_intel_verify(struct intel_ucode_header *hdr)
+{
+       uint32_t *data = (uint32_t *)hdr;
+       size_t total_size;
+       uint32_t sum;
+       int i;
+
+       CTASSERT(sizeof(struct intel_ucode_header) == 48);
+
+       if ((paddr_t)data % 16 != 0) {
+               DPRINTF(("%s: misaligned microcode update\n", __func__));
+               return 1;
+       }
+       if (hdr->loader_rev != 1) {
+               DPRINTF(("%s: unsupported loader rev\n", __func__));
+               return 1;
+       }
+
+       if (hdr->data_size)
+               total_size = hdr->total_size;
+       else
+               total_size = INTEL_UCODE_DEFAULT_DATA_SIZE +
+                   sizeof(struct intel_ucode_header);
+       if (total_size % 4 != 0) {
+               DPRINTF(("%s: inconsistent size\n", __func__));
+               return 1;
+       }
+
+       sum = 0;
+       for (i = 0; i < total_size / 4; i++)
+               sum += data[i];
+       if (sum != 0) {
+               DPRINTF(("%s: wrong checksum (%#x)\n", __func__, sum));
+               return 1;
+       }
+
+       return 0;
+}
+
+int
+cpu_ucode_intel_match(struct intel_ucode_header *hdr,
+    uint32_t processor_sig, uint32_t processor_mask,
+    uint32_t ucode_revision)
+{
+       struct intel_ucode_ext_sig_header *ehdr;
+       struct intel_ucode_ext_sig *esig;
+       uint32_t data_size, total_size;
+       unsigned i;
+
+       data_size = hdr->data_size;
+       total_size = hdr->total_size;
+
+       /*
+        * Older microcode has an empty length.  In that case we
+        * have to use the default length of 2000.
+        */
+       if (!data_size) {
+               data_size = INTEL_UCODE_DEFAULT_DATA_SIZE;
+               total_size = INTEL_UCODE_DEFAULT_DATA_SIZE +
+                   sizeof(struct intel_ucode_header);
+       }
+
+       if (ucode_revision > hdr->update_revision)
+               return 0;
+       if (hdr->processor_sig == processor_sig &&
+           (hdr->processor_flags & processor_mask))
+               return 1;
+       if (total_size <= sizeof(struct intel_ucode_header) +
+           data_size + sizeof(struct intel_ucode_ext_sig_header))
+               return 0;
+
+       ehdr = (void *)((char *)hdr + sizeof(struct intel_ucode_header) +
+           data_size);
+       esig = (void *)&ehdr[1];
+       for (i = 0; i < ehdr->ext_sig_count; i++) {
+               if (esig[i].processor_sig == processor_sig &&
+                   (esig[i].processor_flags & processor_mask))
+                       return 1;
+       }
+
+       return 0;
+}
+
+uint32_t
+cpu_ucode_intel_rev(void)
+{
+       uint32_t eax, ebx, ecx, edx;
+       uint64_t rev;
+
+       wrmsr(MSR_BIOS_SIGN, 0);
+       CPUID(1, eax, ebx, ecx, edx);
+       rev = rdmsr(MSR_BIOS_SIGN);
+       return rev >> 32;
+}
index df903be..94a7df3 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: biosvar.h,v 1.66 2017/06/20 12:39:20 tom Exp $        */
+/*     $OpenBSD: biosvar.h,v 1.67 2018/08/23 14:47:52 jsg Exp $        */
 
 /*
  * Copyright (c) 1997-1999 Michael Shalayeff
@@ -238,6 +238,12 @@ typedef struct _bios_efiinfo {
        uint32_t        fb_reserved_mask;
 } __packed bios_efiinfo_t;
 
+#define        BOOTARG_UCODE 12
+typedef struct _bios_ucode {
+       uint64_t        uc_addr;
+       uint64_t        uc_size;
+} __packed bios_ucode_t;
+
 #if defined(_KERNEL) || defined (_STANDALONE)
 
 #ifdef _LOCORE
@@ -289,6 +295,7 @@ void bios32_cleanup(void);
 extern u_int bootapiver;
 extern bios_memmap_t *bios_memmap;
 extern bios_efiinfo_t *bios_efiinfo;
+extern bios_ucode_t *bios_ucode;
 extern void *bios_smpinfo;
 extern bios_pciinfo_t *bios_pciinfo;
 
index 4f52ffb..78d368d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cpufunc.h,v 1.30 2018/07/30 14:19:12 kettenis Exp $   */
+/*     $OpenBSD: cpufunc.h,v 1.31 2018/08/23 14:47:52 jsg Exp $        */
 /*     $NetBSD: cpufunc.h,v 1.8 1994/10/27 04:15:59 cgd Exp $  */
 
 /*
@@ -280,6 +280,8 @@ breakpoint(void)
 }
 
 void amd64_errata(struct cpu_info *);
+void cpu_ucode_setup(void);
+void cpu_ucode_apply(struct cpu_info *);
 
 struct cpu_info_full;
 void cpu_enter_pages(struct cpu_info_full *);
index d9d6191..edef12c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: specialreg.h,v 1.70 2018/08/21 12:44:13 jsg Exp $     */
+/*     $OpenBSD: specialreg.h,v 1.71 2018/08/23 14:47:52 jsg Exp $     */
 /*     $NetBSD: specialreg.h,v 1.7 1994/10/27 04:16:26 cgd Exp $       */
 
 /*-
 #define        P5MSR_CTRSEL            0x011   /* P5 only (trap on P6) */
 #define        P5MSR_CTR0              0x012   /* P5 only (trap on P6) */
 #define        P5MSR_CTR1              0x013   /* P5 only (trap on P6) */
+#define MSR_PLATFORM_ID                0x017   /* Platform ID for microcode */
 #define MSR_APICBASE           0x01b
 #define        APICBASE_BSP            0x100
 #define APICBASE_ENABLE_X2APIC 0x400
index b1ef8d8..4bb6d6b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: conf.c,v 1.64 2018/08/10 16:43:54 jsing Exp $ */
+/*     $OpenBSD: conf.c,v 1.65 2018/08/23 14:47:52 jsg Exp $   */
 
 /*
  * Copyright (c) 1996 Michael Shalayeff
@@ -41,7 +41,7 @@
 #include <dev/cons.h>
 #include "debug.h"
 
-const char version[] = "3.33";
+const char version[] = "3.34";
 int    debug = 1;
 
 
index df50d2e..909fd60 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: conf.c,v 1.32 2018/07/11 18:08:05 mlarkin Exp $       */
+/*     $OpenBSD: conf.c,v 1.33 2018/08/23 14:47:52 jsg Exp $   */
 
 /*
  * Copyright (c) 2004 Tom Cosgrove
@@ -42,7 +42,7 @@
 #include <dev/cons.h>
 #include "debug.h"
 
-const char version[] = "3.29";
+const char version[] = "3.30";
 int    debug = 1;
 
 void (*sa_cleanup)(void) = NULL;
index 4364a3c..4049f8b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: exec_i386.c,v 1.44 2016/09/11 17:52:47 jsing Exp $    */
+/*     $OpenBSD: exec_i386.c,v 1.45 2018/08/23 14:47:52 jsg Exp $      */
 
 /*
  * Copyright (c) 1997-1998 Michael Shalayeff
 #include <dev/cons.h>
 #include <lib/libsa/loadfile.h>
 #include <machine/biosvar.h>
+#include <machine/specialreg.h>
 #include <stand/boot/bootarg.h>
 
+#include "cmd.h"
 #include "disk.h"
 #include "libsa.h"
 
@@ -51,6 +53,9 @@
 typedef void (*startfuncp)(int, int, int, int, int, int, int, int)
     __attribute__ ((noreturn));
 
+void ucode_load(void);
+extern struct cmd_state cmd;
+
 char *bootmac = NULL;
 
 void
@@ -99,6 +104,8 @@ run_loadfile(u_long *marks, int howto)
        bcopy(bootdev_dip->disklabel.d_uid, &bootduid.duid, sizeof(bootduid));
        addbootarg(BOOTARG_BOOTDUID, sizeof(bootduid), &bootduid);
 
+       ucode_load();
+
 #ifdef SOFTRAID
        if (bootdev_dip->sr_vol != NULL) {
                bv = bootdev_dip->sr_vol;
@@ -144,3 +151,58 @@ run_loadfile(u_long *marks, int howto)
        /* not reached */
 #endif
 }
+
+void
+ucode_load(void)
+{
+       uint32_t model, family, stepping;
+       uint32_t dummy, signature;
+       uint32_t vendor[4];
+       bios_ucode_t uc;
+       struct stat sb;
+       char path[128];
+       size_t buflen;
+       char *buf;
+       int fd;
+
+       CPUID(0, dummy, vendor[0], vendor[2], vendor[1]);
+       vendor[3] = 0; /* NULL-terminate */
+       if (strcmp((char *)vendor, "GenuineIntel") != 0)
+               return;
+
+       CPUID(1, signature, dummy, dummy, dummy);
+       family = (signature >> 8) & 0x0f;
+       model = (signature >> 4) & 0x0f;
+       if (family == 0x6 || family == 0xf) {
+               family += (signature >> 20) & 0xff;
+               model += ((signature >> 16) & 0x0f) << 4;
+       }
+       stepping = (signature >> 0) & 0x0f;
+
+       snprintf(path, sizeof(path), "%s:/etc/firmware/intel/%02x-%02x-%02x",
+           cmd.bootdev, family, model, stepping);
+
+       fd = open(path, 0);
+       if (fd == -1)
+               return;
+
+       if (fstat(fd, &sb) == -1)
+               return;
+
+       buflen = sb.st_size;
+       if (buflen > 128*1024) {
+               printf("ucode too large\n");
+               return;
+       }
+
+       buf = (char *)(1*1024*1024);
+
+       if (read(fd, buf, buflen) != buflen) {
+               free(buf, buflen);
+               return;
+       }
+
+       uc.uc_addr = (uint64_t)buf;
+       uc.uc_size = (uint64_t)buflen;
+       addbootarg(BOOTARG_UCODE, sizeof(uc), &uc);
+}
index 2ffe11c..8872e6a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: conf.c,v 1.37 2018/07/11 18:08:05 mlarkin Exp $       */
+/*     $OpenBSD: conf.c,v 1.38 2018/08/23 14:47:52 jsg Exp $   */
 
 /*
  * Copyright (c) 2004 Tom Cosgrove
@@ -44,7 +44,7 @@
 #include "pxeboot.h"
 #include "pxe_net.h"
 
-const char version[] = "3.29";
+const char version[] = "3.30";
 int    debug = 1;
 
 void (*sa_cleanup)(void) = pxe_shutdown;