|
@@ -66,7 +66,6 @@ struct microcode_amd {
|
|
|
unsigned int mpb[0];
|
|
|
};
|
|
|
|
|
|
-#define UCODE_MAX_SIZE 2048
|
|
|
#define UCODE_CONTAINER_SECTION_HDR 8
|
|
|
#define UCODE_CONTAINER_HEADER_SIZE 12
|
|
|
|
|
@@ -155,31 +154,60 @@ static int apply_microcode_amd(int cpu)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static unsigned int verify_ucode_size(int cpu, const u8 *buf, unsigned int size)
|
|
|
+{
|
|
|
+ struct cpuinfo_x86 *c = &cpu_data(cpu);
|
|
|
+ unsigned int max_size, actual_size;
|
|
|
+
|
|
|
+#define F1XH_MPB_MAX_SIZE 2048
|
|
|
+#define F14H_MPB_MAX_SIZE 1824
|
|
|
+#define F15H_MPB_MAX_SIZE 4096
|
|
|
+
|
|
|
+ switch (c->x86) {
|
|
|
+ case 0x14:
|
|
|
+ max_size = F14H_MPB_MAX_SIZE;
|
|
|
+ break;
|
|
|
+ case 0x15:
|
|
|
+ max_size = F15H_MPB_MAX_SIZE;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ max_size = F1XH_MPB_MAX_SIZE;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ actual_size = buf[4] + (buf[5] << 8);
|
|
|
+
|
|
|
+ if (actual_size > size || actual_size > max_size) {
|
|
|
+ pr_err("section size mismatch\n");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ return actual_size;
|
|
|
+}
|
|
|
+
|
|
|
static struct microcode_header_amd *
|
|
|
-get_next_ucode(const u8 *buf, unsigned int size, unsigned int *mc_size)
|
|
|
+get_next_ucode(int cpu, const u8 *buf, unsigned int size, unsigned int *mc_size)
|
|
|
{
|
|
|
- struct microcode_header_amd *mc;
|
|
|
- unsigned int total_size;
|
|
|
+ struct microcode_header_amd *mc = NULL;
|
|
|
+ unsigned int actual_size = 0;
|
|
|
|
|
|
if (buf[0] != UCODE_UCODE_TYPE) {
|
|
|
pr_err("invalid type field in container file section header\n");
|
|
|
- return NULL;
|
|
|
+ goto out;
|
|
|
}
|
|
|
|
|
|
- total_size = buf[4] + (buf[5] << 8);
|
|
|
-
|
|
|
- if (total_size > size || total_size > UCODE_MAX_SIZE) {
|
|
|
- pr_err("section size mismatch\n");
|
|
|
- return NULL;
|
|
|
- }
|
|
|
+ actual_size = verify_ucode_size(cpu, buf, size);
|
|
|
+ if (!actual_size)
|
|
|
+ goto out;
|
|
|
|
|
|
- mc = vzalloc(UCODE_MAX_SIZE);
|
|
|
+ mc = vzalloc(actual_size);
|
|
|
if (!mc)
|
|
|
- return NULL;
|
|
|
+ goto out;
|
|
|
|
|
|
- get_ucode_data(mc, buf + UCODE_CONTAINER_SECTION_HDR, total_size);
|
|
|
- *mc_size = total_size + UCODE_CONTAINER_SECTION_HDR;
|
|
|
+ get_ucode_data(mc, buf + UCODE_CONTAINER_SECTION_HDR, actual_size);
|
|
|
+ *mc_size = actual_size + UCODE_CONTAINER_SECTION_HDR;
|
|
|
|
|
|
+out:
|
|
|
return mc;
|
|
|
}
|
|
|
|
|
@@ -234,7 +262,7 @@ generic_load_microcode(int cpu, const u8 *data, size_t size)
|
|
|
leftover = size - offset;
|
|
|
|
|
|
while (leftover) {
|
|
|
- mc_hdr = get_next_ucode(ucode_ptr, leftover, &mc_size);
|
|
|
+ mc_hdr = get_next_ucode(cpu, ucode_ptr, leftover, &mc_size);
|
|
|
if (!mc_hdr)
|
|
|
break;
|
|
|
|