unsigned int mpb[0];
};
-#define UCODE_MAX_SIZE 2048
#define UCODE_CONTAINER_SECTION_HDR 8
#define UCODE_CONTAINER_HEADER_SIZE 12
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;
}
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;