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.
18 #include <console/console.h>
19 #include <cpu/x86/msr.h>
20 #include <cpu/amd/microcode.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
38 * STRUCTURE OF A MICROCODE (UCODE) 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
55 * [8-11] Size (n) in bytes of variable portion of container header
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
89 uint16_t mc_patch_data_id
;
90 uint8_t mc_patch_data_len
;
93 uint32_t mc_patch_data_checksum
;
98 uint16_t processor_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];
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
;
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 */
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
;
148 /* Container Header */
149 container_hdr_id
= read32(c
);
150 if (container_hdr_id
!= UCODE_MAGIC
) {
151 UCODE_DEBUG("Invalid container header ID\n");
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
);
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
[] = {
183 "microcode_amd_fam15h.bin",
186 void amd_update_microcode_from_cbfs(uint32_t equivalent_processor_rev_id
)
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");
200 ucode
= cbfs_boot_map_with_leak(microcode_cbfs_file
[i
],
201 CBFS_TYPE_MICROCODE
, &ucode_len
);
203 UCODE_DEBUG("microcode file not found. Skipping updates.\n");
208 amd_update_microcode(ucode
, ucode_len
, equivalent_processor_rev_id
);