tree: drop last paragraph of GPL copyright header
[coreboot.git] / src / cpu / amd / microcode / microcode.c
blob37d395a5607ad0fcb585e4c36a161d51e8797900
1 /*
2 * This file is part of the coreboot project.
4 * Copyright (C) 2007 Advanced Micro Devices, Inc.
5 * Copyright (C) 2015 Raptor Engineering
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
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.
17 #include <stdint.h>
18 #include <console/console.h>
19 #include <cpu/x86/msr.h>
20 #include <cpu/amd/microcode.h>
21 #include <cbfs.h>
22 #include <arch/io.h>
24 #define UCODE_DEBUG(fmt, args...) \
25 do { printk(BIOS_DEBUG, "[microcode] "fmt, ##args); } while(0)
27 #define UCODE_MAGIC 0x00414d44
28 #define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000
29 #define UCODE_SECTION_START_ID 0x00000001
30 #define UCODE_MAGIC 0x00414d44
32 #define F1XH_MPB_MAX_SIZE 2048
33 #define F15H_MPB_MAX_SIZE 4096
34 #define CONT_HDR 12
35 #define SECT_HDR 8
38 * STRUCTURE OF A MICROCODE (UCODE) FILE
39 * Container Header
40 * Section Header
41 * Microcode Header
42 * Microcode "Blob"
43 * Section Header
44 * Microcode Header
45 * Microcode "Blob"
46 * ...
47 * ...
48 * (end of file)
51 * CONTAINER HEADER (offset 0 bytes from start of file)
52 * Total size = fixed size (12 bytes) + variable size
53 * [0:3] 32-bit unique ID
54 * [4:7] don't-care
55 * [8-11] Size (n) in bytes of variable portion of container header
56 * [12-n] don't-care
58 * SECTION HEADER (offset += 12+n)
59 * Total size = 8 bytes
60 * [0:3] Unique identifier signaling start of section (0x00000001)
61 * [4:7] Total size (m) of following microcode section, including microcode header
63 * MICROCODE HEADER (offset += 8)
64 * Total size = 64 bytes
65 * [0:3] Data code (32 bits)
66 * [4:7] Patch ID (32 bits)
67 * [8:9] Microcode patch data ID (16 bits)
68 * [10] c patch data length (8 bits)
69 * [11] init flag (8 bits)
70 * [12:15] ucode patch data cksum (32 bits)
71 * [16:19] nb dev ID (32 bits)
72 * [20:23] sb dev ID (32 bits)
73 * [24:25] Processor rev ID (16 bits)
74 * [26] nb revision ID (8 bits)
75 * [27] sb revision ID (8 bits)
76 * [28] BIOS API revision (8 bits)
77 * [29-31] Reserved 1 (array of three 8-bit values)
78 * [32-63] Match reg (array of eight 32-bit values)
80 * MICROCODE BLOB (offset += 64)
81 * Total size = m bytes
85 struct microcode {
86 uint32_t data_code;
87 uint32_t patch_id;
89 uint16_t mc_patch_data_id;
90 uint8_t mc_patch_data_len;
91 uint8_t init_flag;
93 uint32_t mc_patch_data_checksum;
95 uint32_t nb_dev_id;
96 uint32_t sb_dev_id;
98 uint16_t processor_rev_id;
99 uint8_t nb_rev_id;
100 uint8_t sb_rev_id;
102 uint8_t bios_api_rev;
103 uint8_t reserved1[3];
105 uint32_t match_reg[8];
107 uint8_t m_patch_data[896];
108 uint8_t resv2[896];
110 uint8_t x86_code_present;
111 uint8_t x86_code_entry[191];
114 static void apply_microcode_patch(const struct microcode *m)
116 uint32_t new_patch_id;
117 msr_t msr;
119 /* apply patch */
120 msr.hi = 0;
121 msr.lo = (uint32_t)m;
123 wrmsr(0xc0010020, msr);
125 UCODE_DEBUG("patch id to apply = 0x%08x\n", m->patch_id);
127 /* read the patch_id again */
128 msr = rdmsr(0x8b);
129 new_patch_id = msr.lo;
131 UCODE_DEBUG("updated to patch id = 0x%08x %s\n", new_patch_id ,
132 (new_patch_id == m->patch_id) ? "success" : "fail");
135 static void amd_update_microcode(const void *ucode, size_t ucode_len,
136 uint32_t equivalent_processor_rev_id)
138 const struct microcode *m;
139 const uint8_t *c = ucode;
140 const uint8_t *ucode_end = (uint8_t*)ucode + ucode_len;
141 const uint8_t *cur_section_hdr;
143 uint32_t container_hdr_id;
144 uint32_t container_hdr_size;
145 uint32_t blob_size;
146 uint32_t sec_hdr_id;
148 /* Container Header */
149 container_hdr_id = read32(c);
150 if (container_hdr_id != UCODE_MAGIC) {
151 UCODE_DEBUG("Invalid container header ID\n");
152 return;
155 container_hdr_size = read32(c + 8);
156 cur_section_hdr = c + CONT_HDR + container_hdr_size;
158 /* Read in first section header ID */
159 sec_hdr_id = read32(cur_section_hdr);
160 c = cur_section_hdr + 4;
162 /* Loop through sections */
163 while (sec_hdr_id == UCODE_SECTION_START_ID &&
164 c <= (ucode_end - F15H_MPB_MAX_SIZE)) {
166 blob_size = read32(c);
168 m = (struct microcode *)(c + 4);
170 if (m->processor_rev_id == equivalent_processor_rev_id) {
171 apply_microcode_patch(m);
172 break;
175 cur_section_hdr = c + 4 + blob_size;
176 sec_hdr_id = read32(cur_section_hdr);
177 c = cur_section_hdr + 4;
181 static const char *microcode_cbfs_file[] = {
182 "microcode_amd.bin",
183 "microcode_amd_fam15h.bin",
186 void amd_update_microcode_from_cbfs(uint32_t equivalent_processor_rev_id)
188 const void *ucode;
189 size_t ucode_len;
191 uint32_t i;
193 for (i = 0; i < ARRAY_SIZE(microcode_cbfs_file); i++)
195 if (equivalent_processor_rev_id == 0) {
196 UCODE_DEBUG("rev id not found. Skipping microcode patch!\n");
197 return;
200 ucode = cbfs_boot_map_with_leak(microcode_cbfs_file[i],
201 CBFS_TYPE_MICROCODE, &ucode_len);
202 if (!ucode) {
203 UCODE_DEBUG("microcode file not found. Skipping updates.\n");
205 return;
208 amd_update_microcode(ucode, ucode_len, equivalent_processor_rev_id);