aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/microcode_amd.c
diff options
context:
space:
mode:
authorBorislav Petkov <borislav.petkov@amd.com>2011-02-10 06:19:47 -0500
committerBorislav Petkov <borislav.petkov@amd.com>2011-02-10 06:24:03 -0500
commit44d60c0f5c58c2168f31df9a481761451840eb54 (patch)
treeda0e3401dd9aa206f8e3d2562799d4c21aa4cf56 /arch/x86/kernel/microcode_amd.c
parent258721ef34fce97a7a6ca9cebebb303827645868 (diff)
x86, microcode, AMD: Extend ucode size verification
The different families have a different max size for the ucode patch, adjust size checking to the family we're running on. Also, do not vzalloc the max size of the ucode but only the actual size that is passed on from the firmware loader. Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
Diffstat (limited to 'arch/x86/kernel/microcode_amd.c')
-rw-r--r--arch/x86/kernel/microcode_amd.c60
1 files changed, 44 insertions, 16 deletions
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c
index adbcef4f6333..9fb8405451c5 100644
--- a/arch/x86/kernel/microcode_amd.c
+++ b/arch/x86/kernel/microcode_amd.c
@@ -66,7 +66,6 @@ struct microcode_amd {
66 unsigned int mpb[0]; 66 unsigned int mpb[0];
67}; 67};
68 68
69#define UCODE_MAX_SIZE 2048
70#define UCODE_CONTAINER_SECTION_HDR 8 69#define UCODE_CONTAINER_SECTION_HDR 8
71#define UCODE_CONTAINER_HEADER_SIZE 12 70#define UCODE_CONTAINER_HEADER_SIZE 12
72 71
@@ -155,31 +154,60 @@ static int apply_microcode_amd(int cpu)
155 return 0; 154 return 0;
156} 155}
157 156
157static unsigned int verify_ucode_size(int cpu, const u8 *buf, unsigned int size)
158{
159 struct cpuinfo_x86 *c = &cpu_data(cpu);
160 unsigned int max_size, actual_size;
161
162#define F1XH_MPB_MAX_SIZE 2048
163#define F14H_MPB_MAX_SIZE 1824
164#define F15H_MPB_MAX_SIZE 4096
165
166 switch (c->x86) {
167 case 0x14:
168 max_size = F14H_MPB_MAX_SIZE;
169 break;
170 case 0x15:
171 max_size = F15H_MPB_MAX_SIZE;
172 break;
173 default:
174 max_size = F1XH_MPB_MAX_SIZE;
175 break;
176 }
177
178 actual_size = buf[4] + (buf[5] << 8);
179
180 if (actual_size > size || actual_size > max_size) {
181 pr_err("section size mismatch\n");
182 return 0;
183 }
184
185 return actual_size;
186}
187
158static struct microcode_header_amd * 188static struct microcode_header_amd *
159get_next_ucode(const u8 *buf, unsigned int size, unsigned int *mc_size) 189get_next_ucode(int cpu, const u8 *buf, unsigned int size, unsigned int *mc_size)
160{ 190{
161 struct microcode_header_amd *mc; 191 struct microcode_header_amd *mc = NULL;
162 unsigned int total_size; 192 unsigned int actual_size = 0;
163 193
164 if (buf[0] != UCODE_UCODE_TYPE) { 194 if (buf[0] != UCODE_UCODE_TYPE) {
165 pr_err("invalid type field in container file section header\n"); 195 pr_err("invalid type field in container file section header\n");
166 return NULL; 196 goto out;
167 } 197 }
168 198
169 total_size = buf[4] + (buf[5] << 8); 199 actual_size = verify_ucode_size(cpu, buf, size);
170 200 if (!actual_size)
171 if (total_size > size || total_size > UCODE_MAX_SIZE) { 201 goto out;
172 pr_err("section size mismatch\n");
173 return NULL;
174 }
175 202
176 mc = vzalloc(UCODE_MAX_SIZE); 203 mc = vzalloc(actual_size);
177 if (!mc) 204 if (!mc)
178 return NULL; 205 goto out;
179 206
180 get_ucode_data(mc, buf + UCODE_CONTAINER_SECTION_HDR, total_size); 207 get_ucode_data(mc, buf + UCODE_CONTAINER_SECTION_HDR, actual_size);
181 *mc_size = total_size + UCODE_CONTAINER_SECTION_HDR; 208 *mc_size = actual_size + UCODE_CONTAINER_SECTION_HDR;
182 209
210out:
183 return mc; 211 return mc;
184} 212}
185 213
@@ -234,7 +262,7 @@ generic_load_microcode(int cpu, const u8 *data, size_t size)
234 leftover = size - offset; 262 leftover = size - offset;
235 263
236 while (leftover) { 264 while (leftover) {
237 mc_hdr = get_next_ucode(ucode_ptr, leftover, &mc_size); 265 mc_hdr = get_next_ucode(cpu, ucode_ptr, leftover, &mc_size);
238 if (!mc_hdr) 266 if (!mc_hdr)
239 break; 267 break;
240 268