1 /* $NetBSD: cpu_ucode.c,v 1.4 2013/07/06 12:03:11 gdt Exp $ */ 2 /* 3 * Copyright (c) 2012 The NetBSD Foundation, Inc. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to The NetBSD Foundation 7 * by Christoph Egger. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 __KERNEL_RCSID(0, "$NetBSD: cpu_ucode.c,v 1.4 2013/07/06 12:03:11 gdt Exp $"); 33 34 #include "opt_cpu_ucode.h" 35 #include "opt_compat_netbsd.h" 36 37 #include <sys/param.h> 38 #include <sys/cpuio.h> 39 #include <sys/cpu.h> 40 41 #include <dev/firmload.h> 42 43 #include <machine/cpuvar.h> 44 #include <machine/cputypes.h> 45 46 #include <x86/cpu_ucode.h> 47 48 static struct cpu_ucode_softc ucode_softc; 49 50 int 51 cpu_ucode_get_version(struct cpu_ucode_version *data) 52 { 53 54 switch (cpu_vendor) { 55 case CPUVENDOR_AMD: 56 return cpu_ucode_amd_get_version(data); 57 case CPUVENDOR_INTEL: 58 return cpu_ucode_intel_get_version(data); 59 default: 60 return EOPNOTSUPP; 61 } 62 63 return 0; 64 } 65 66 #ifdef COMPAT_60 67 int 68 compat6_cpu_ucode_get_version(struct compat6_cpu_ucode *data) 69 { 70 71 switch (cpu_vendor) { 72 case CPUVENDOR_AMD: 73 return compat6_cpu_ucode_amd_get_version(data); 74 default: 75 return EOPNOTSUPP; 76 } 77 78 return 0; 79 } 80 #endif /* COMPAT60 */ 81 82 int 83 cpu_ucode_md_open(firmware_handle_t *fwh, int loader_version, const char *fwname) 84 { 85 switch (cpu_vendor) { 86 case CPUVENDOR_AMD: 87 return cpu_ucode_amd_firmware_open(fwh, fwname); 88 case CPUVENDOR_INTEL: 89 return cpu_ucode_intel_firmware_open(fwh, fwname); 90 default: 91 return EOPNOTSUPP; 92 } 93 } 94 95 int 96 cpu_ucode_apply(const struct cpu_ucode *data) 97 { 98 struct cpu_ucode_softc *sc = &ucode_softc; 99 int error; 100 101 sc->loader_version = data->loader_version; 102 103 error = cpu_ucode_load(sc, data->fwname); 104 if (error) 105 return error; 106 107 switch (cpu_vendor) { 108 case CPUVENDOR_AMD: 109 error = cpu_ucode_amd_apply(sc, data->cpu_nr); 110 break; 111 case CPUVENDOR_INTEL: 112 error = cpu_ucode_intel_apply(sc, data->cpu_nr); 113 break; 114 default: 115 return EOPNOTSUPP; 116 } 117 118 if (sc->sc_blob != NULL) 119 firmware_free(sc->sc_blob, 0); 120 sc->sc_blob = NULL; 121 sc->sc_blobsize = 0; 122 return error; 123 } 124 125 #ifdef COMPAT_60 126 int 127 compat6_cpu_ucode_apply(const struct compat6_cpu_ucode *data) 128 { 129 struct cpu_ucode_softc *sc = &ucode_softc; 130 int error; 131 132 if (cpu_vendor != CPUVENDOR_AMD) 133 return EOPNOTSUPP; 134 135 sc->loader_version = CPU_UCODE_LOADER_AMD; 136 error = cpu_ucode_load(sc, data->fwname); 137 if (error) 138 return error; 139 140 error = cpu_ucode_amd_apply(sc, CPU_UCODE_ALL_CPUS); 141 142 if (sc->sc_blob != NULL) 143 firmware_free(sc->sc_blob, 0); 144 sc->sc_blob = NULL; 145 sc->sc_blobsize = 0; 146 return error; 147 } 148 #endif /* COMPAT60 */ 149