1 /*- 2 * Copyright (c) 2012 Andriy Gapon <avg@FreeBSD.org>. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include <sys/types.h> 27 #include <sys/stat.h> 28 #include <sys/mman.h> 29 #include <sys/ioctl.h> 30 #include <sys/ioccom.h> 31 #include <sys/cpuctl.h> 32 33 #include <machine/cpufunc.h> 34 #include <machine/specialreg.h> 35 36 #include <x86/ucode.h> 37 38 #include <assert.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <string.h> 42 #include <unistd.h> 43 #include <fcntl.h> 44 #include <err.h> 45 46 #include "cpucontrol.h" 47 #include "amd.h" 48 49 int 50 amd10h_probe(int fd) 51 { 52 char vendor[13]; 53 cpuctl_cpuid_args_t idargs; 54 uint32_t family; 55 uint32_t signature; 56 int error; 57 58 idargs.level = 0; 59 error = ioctl(fd, CPUCTL_CPUID, &idargs); 60 if (error < 0) { 61 WARN(0, "ioctl()"); 62 return (1); 63 } 64 ((uint32_t *)vendor)[0] = idargs.data[1]; 65 ((uint32_t *)vendor)[1] = idargs.data[3]; 66 ((uint32_t *)vendor)[2] = idargs.data[2]; 67 vendor[12] = '\0'; 68 if (strncmp(vendor, AMD_VENDOR_ID, sizeof(AMD_VENDOR_ID)) != 0) 69 return (1); 70 71 idargs.level = 1; 72 error = ioctl(fd, CPUCTL_CPUID, &idargs); 73 if (error < 0) { 74 WARN(0, "ioctl()"); 75 return (1); 76 } 77 signature = idargs.data[0]; 78 family = ((signature >> 8) & 0x0f) + ((signature >> 20) & 0xff); 79 if (family < 0x10) 80 return (1); 81 return (0); 82 } 83 84 void 85 amd10h_update(const struct ucode_update_params *params) 86 { 87 cpuctl_cpuid_args_t idargs; 88 cpuctl_msr_args_t msrargs; 89 cpuctl_update_args_t args; 90 const uint8_t *fw_image; 91 const char *dev, *path; 92 const void *selected_fw; 93 size_t fw_size; 94 size_t selected_size; 95 uint32_t revision; 96 uint32_t new_rev; 97 uint32_t signature; 98 int devfd; 99 int error; 100 101 dev = params->dev_path; 102 path = params->fw_path; 103 devfd = params->devfd; 104 fw_image = params->fwimage; 105 fw_size = params->fwsize; 106 107 assert(path); 108 assert(dev); 109 110 idargs.level = 1; 111 error = ioctl(devfd, CPUCTL_CPUID, &idargs); 112 if (error < 0) { 113 WARN(0, "ioctl()"); 114 goto done; 115 } 116 signature = idargs.data[0]; 117 118 msrargs.msr = MSR_BIOS_SIGN; 119 error = ioctl(devfd, CPUCTL_RDMSR, &msrargs); 120 if (error < 0) { 121 WARN(0, "ioctl(%s)", dev); 122 goto done; 123 } 124 revision = (uint32_t)msrargs.data; 125 126 selected_fw = ucode_amd_find(path, signature, revision, fw_image, 127 fw_size, &selected_size); 128 129 if (selected_fw != NULL) { 130 WARNX(1, "selected ucode size is %zu", selected_size); 131 fprintf(stderr, "%s: updating cpu %s to revision %#x... ", 132 path, dev, revision); 133 134 args.data = __DECONST(void *, selected_fw); 135 args.size = selected_size; 136 error = ioctl(devfd, CPUCTL_UPDATE, &args); 137 if (error < 0) { 138 fprintf(stderr, "failed.\n"); 139 warn("ioctl()"); 140 goto done; 141 } 142 fprintf(stderr, "done.\n"); 143 } 144 145 msrargs.msr = MSR_BIOS_SIGN; 146 error = ioctl(devfd, CPUCTL_RDMSR, &msrargs); 147 if (error < 0) { 148 WARN(0, "ioctl(%s)", dev); 149 goto done; 150 } 151 new_rev = (uint32_t)msrargs.data; 152 if (new_rev != revision) 153 WARNX(0, "revision after update %#x", new_rev); 154 155 done: 156 return; 157 } 158