1/* $NetBSD: cpu_ucode.c,v 1.5 2015/01/07 07:05:48 ozaki-r 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.5 2015/01/07 07:05:48 ozaki-r 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
48static struct cpu_ucode_softc ucode_softc;
49
50int
51cpu_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
67int
68compat6_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
82int
83cpu_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
95int
96cpu_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, sc->sc_blobsize);
120 sc->sc_blob = NULL;
121 sc->sc_blobsize = 0;
122 return error;
123}
124
125#ifdef COMPAT_60
126int
127compat6_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, sc->sc_blobsize);
144 sc->sc_blob = NULL;
145 sc->sc_blobsize = 0;
146 return error;
147}
148#endif /* COMPAT60 */
149