Alexandru Gagniuc | e644bad | 2012-08-07 19:38:32 -0500 | [diff] [blame] | 1 | /* |
| 2 | * This file is part of the coreboot project. |
| 3 | * |
| 4 | * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com> |
| 5 | * |
| 6 | * This program is free software: you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License as published by |
| 8 | * the Free Software Foundation, either version 2 of the License, or |
| 9 | * (at your option) any later version. |
| 10 | * |
| 11 | * This program is distributed in the hope that it will be useful, |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | * GNU General Public License for more details. |
Alexandru Gagniuc | e644bad | 2012-08-07 19:38:32 -0500 | [diff] [blame] | 15 | */ |
| 16 | |
| 17 | #include "update_ucode.h" |
| 18 | #include <cpu/x86/msr.h> |
| 19 | #include <console/console.h> |
| 20 | #include <stddef.h> |
| 21 | #include <cpu/cpu.h> |
| 22 | #include <arch/cpu.h> |
| 23 | #include <cbfs.h> |
| 24 | |
| 25 | static ucode_update_status nano_apply_ucode(const nano_ucode_header *ucode) |
| 26 | { |
| 27 | printk(BIOS_SPEW, "Attempting to apply microcode update\n"); |
| 28 | |
| 29 | msr_t msr; |
| 30 | /* Address of ucode block goes in msr.lo for 32-bit mode |
| 31 | * Now remember, we need to pass the address of the actual microcode, |
| 32 | * not the header. The header is just there to help us. */ |
| 33 | msr.lo = (unsigned int)(&(ucode->ucode_start)); |
| 34 | msr.hi = 0; |
| 35 | wrmsr(MSR_IA32_BIOS_UPDT_TRIG, msr); |
| 36 | |
Martin Roth | 4c3ab73 | 2013-07-08 16:23:54 -0600 | [diff] [blame] | 37 | /* Let's see if we updated successfully */ |
Alexandru Gagniuc | e644bad | 2012-08-07 19:38:32 -0500 | [diff] [blame] | 38 | msr = rdmsr(MSR_UCODE_UPDATE_STATUS); |
| 39 | |
| 40 | return msr.lo & 0x07; |
| 41 | } |
| 42 | |
| 43 | static void nano_print_ucode_info(const nano_ucode_header *ucode) |
| 44 | { |
| 45 | printk(BIOS_SPEW, "Microcode update information:\n"); |
| 46 | printk(BIOS_SPEW, "Name: %8s\n", ucode->name ); |
| 47 | printk(BIOS_SPEW, "Date: %u/%u/%u\n", ucode->month, |
| 48 | ucode->day, ucode->year ); |
| 49 | } |
| 50 | |
| 51 | static ucode_validity nano_ucode_is_valid(const nano_ucode_header *ucode) |
| 52 | { |
| 53 | /* We must have a valid signature */ |
| 54 | if(ucode->signature != NANO_UCODE_SIGNATURE) |
| 55 | return NANO_UCODE_SIGNATURE_ERROR; |
| 56 | /* The size of the head must be exactly 12 double words */ |
| 57 | if( (ucode->total_size - ucode->payload_size) != NANO_UCODE_HEADER_SIZE) |
| 58 | return NANO_UCODE_WRONG_SIZE; |
| 59 | |
| 60 | /* How about a checksum ? Checksum must be 0 |
| 61 | * Two's complement done over the entire file, including the header */ |
| 62 | int i; |
| 63 | u32 check = 0; |
| 64 | u32 *raw = (void*) ucode; |
| 65 | for(i = 0 ; i < ((ucode->total_size) >> 2); i++) { |
| 66 | check += raw[i]; |
| 67 | } |
| 68 | if(check != 0) |
| 69 | return NANO_UCODE_CHECKSUM_FAIL; |
| 70 | /* Made it here huh? Then it looks valid to us. |
| 71 | * If there's anything else wrong, the CPU will reject the update */ |
| 72 | return NANO_UCODE_VALID; |
| 73 | } |
| 74 | |
| 75 | static void nano_print_ucode_status(ucode_update_status stat) |
| 76 | { |
| 77 | switch(stat) |
| 78 | { |
| 79 | case UCODE_UPDATE_SUCCESS: |
Martin Roth | 4c3ab73 | 2013-07-08 16:23:54 -0600 | [diff] [blame] | 80 | printk(BIOS_INFO, "Microcode update successful.\n"); |
Alexandru Gagniuc | e644bad | 2012-08-07 19:38:32 -0500 | [diff] [blame] | 81 | break; |
| 82 | case UCODE_UPDATE_FAIL: |
| 83 | printk(BIOS_ALERT, "Microcode update failed, bad environment." |
| 84 | "Update was not applied.\n"); |
| 85 | break; |
| 86 | case UCODE_UPDATE_WRONG_CPU: |
| 87 | printk(BIOS_ALERT, "Update not applicable to this CPU.\n"); |
| 88 | break; |
| 89 | case UCODE_INVALID_UPDATE_BLOCK: |
| 90 | printk(BIOS_ALERT, "Microcode block invalid." |
| 91 | "Update was not applied.\n"); |
| 92 | break; |
| 93 | default: |
| 94 | printk(BIOS_ALERT, "Unknown status. No update applied.\n"); |
| 95 | } |
| 96 | } |
| 97 | |
| 98 | unsigned int nano_update_ucode(void) |
| 99 | { |
| 100 | size_t i; |
| 101 | unsigned int n_updates = 0; |
Alexandru Gagniuc | e644bad | 2012-08-07 19:38:32 -0500 | [diff] [blame] | 102 | u32 fms = cpuid_eax(0x1); |
Alexandru Gagniuc | e644bad | 2012-08-07 19:38:32 -0500 | [diff] [blame] | 103 | /* Considering we are running with eXecute-In-Place (XIP), there's no |
| 104 | * need to worry that accessing data from ROM will slow us down. |
| 105 | * Microcode data should be aligned to a 4-byte boundary, but CBFS |
| 106 | * already does that for us (Do you, CBFS?) */ |
Vladimir Serbinenko | 1287416 | 2014-01-12 14:12:15 +0100 | [diff] [blame] | 107 | u32 *ucode_data; |
| 108 | size_t ucode_len; |
| 109 | |
Aaron Durbin | 899d13d | 2015-05-15 23:39:23 -0500 | [diff] [blame] | 110 | ucode_data = cbfs_boot_map_with_leak("cpu_microcode_blob.bin", |
| 111 | CBFS_TYPE_MICROCODE, &ucode_len); |
Vladimir Serbinenko | 1287416 | 2014-01-12 14:12:15 +0100 | [diff] [blame] | 112 | /* Oops, did you forget to include the microcode ? */ |
| 113 | if(ucode_data == NULL) { |
| 114 | printk(BIOS_ALERT, "WARNING: No microcode file found in CBFS. " |
| 115 | "Aborting microcode updates\n"); |
| 116 | return 0; |
| 117 | } |
Alexandru Gagniuc | e644bad | 2012-08-07 19:38:32 -0500 | [diff] [blame] | 118 | |
| 119 | /* We might do a lot of loops searching for the microcode updates, but |
| 120 | * keep in mind, nano_ucode_is_valid searches for the signature before |
| 121 | * doing anything else. */ |
| 122 | for( i = 0; i < (ucode_len >> 2); /* don't increment i here */ ) |
| 123 | { |
| 124 | ucode_update_status stat; |
| 125 | const nano_ucode_header * ucode = (void *)(&ucode_data[i]); |
| 126 | if(nano_ucode_is_valid(ucode) != NANO_UCODE_VALID) { |
| 127 | i++; |
| 128 | continue; |
| 129 | } |
| 130 | /* Since we have a valid microcode, there's no need to search |
| 131 | * in this region, so we restart our search at the end of this |
| 132 | * microcode */ |
| 133 | i += (ucode->total_size >> 2); |
| 134 | /* Is the microcode compatible with our CPU? */ |
| 135 | if(ucode->applicable_fms != fms) continue; |
| 136 | /* For our most curious users */ |
| 137 | nano_print_ucode_info(ucode); |
| 138 | /* The meat of the pie */ |
| 139 | stat = nano_apply_ucode(ucode); |
| 140 | /* The user might want to know how the update went */ |
| 141 | nano_print_ucode_status(stat); |
| 142 | if(stat == UCODE_UPDATE_SUCCESS) n_updates++; |
| 143 | } |
| 144 | |
| 145 | return n_updates; |
| 146 | } |