summaryrefslogtreecommitdiff
path: root/src/cpu/intel/microcode
diff options
context:
space:
mode:
authorAlexandru Gagniuc <mr.nuke.me@gmail.com>2013-12-08 16:30:07 -0600
committerAlexandru Gagniuc <mr.nuke.me@gmail.com>2013-12-17 22:59:19 +0100
commitb1ae0303ce1ae3cb7f5b4f9ded32fac424be5bcb (patch)
tree28f883d6a8a06a2c94d89cb76dce955f23af5a36 /src/cpu/intel/microcode
parent4c37e58ea5afcda9779ac5ea410e84c168461f21 (diff)
cpu/intel: Do not rely on CBFS microcode having a terminator
Up until now, a dummy terminator was required for CBFS microcode files. This was a coreboot only requirement in order to terminate the loop which searches for updates. Figure out where the microcode file ends, and exit the loop if we pass the end of the CBFS without finding any updates. Change-Id: Ib61247e83ae6b67b27fcd61bd40241d4cd7bd246 Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com> Reviewed-on: http://review.coreboot.org/4505 Tested-by: build bot (Jenkins) Reviewed-by: Vladimir Serbinenko <phcoder@gmail.com> Reviewed-by: Aaron Durbin <adurbin@google.com>
Diffstat (limited to 'src/cpu/intel/microcode')
-rw-r--r--src/cpu/intel/microcode/microcode.c47
1 files changed, 31 insertions, 16 deletions
diff --git a/src/cpu/intel/microcode/microcode.c b/src/cpu/intel/microcode/microcode.c
index a68b24d180..83a412673f 100644
--- a/src/cpu/intel/microcode/microcode.c
+++ b/src/cpu/intel/microcode/microcode.c
@@ -115,25 +115,27 @@ void intel_microcode_load_unlocked(const void *microcode_patch)
const void *intel_microcode_find(void)
{
+ struct cbfs_file *microcode_file;
void *microcode_updates;
- u32 eax;
- u32 pf, rev, sig;
+ u32 eax, microcode_len;
+ u32 pf, rev, sig, update_size;
unsigned int x86_model, x86_family;
const struct microcode *m;
- const char *c;
msr_t msr;
#ifdef __PRE_RAM__
- microcode_updates = walkcbfs((char *) MICROCODE_CBFS_FILE);
+ microcode_file = walkcbfs_head((char *) MICROCODE_CBFS_FILE);
#else
- microcode_updates = cbfs_get_file_content(CBFS_DEFAULT_MEDIA,
- MICROCODE_CBFS_FILE,
- CBFS_TYPE_MICROCODE);
+ microcode_file = cbfs_get_file(CBFS_DEFAULT_MEDIA,
+ MICROCODE_CBFS_FILE);
#endif
- if (!microcode_updates)
+ if (!microcode_file)
return NULL;
+ microcode_updates = CBFS_SUBHEADER(microcode_file);
+ microcode_len = ntohl(microcode_file->len);
+
/* CPUID sets MSR 0x8B iff a microcode update has been loaded. */
msr.lo = 0;
msr.hi = 0;
@@ -158,19 +160,32 @@ const void *intel_microcode_find(void)
sig, pf, rev);
#endif
- m = microcode_updates;
- for(c = microcode_updates; m->hdrver; m = (const struct microcode *)c) {
- if ((m->sig == sig) && (m->pf & pf))
- return m;
-
+ while (microcode_len >= sizeof(*m)) {
+ m = microcode_updates;
+ /* Newer microcode updates include a size field, whereas older
+ * containers set it at 0 and are exactly 2048 bytes long */
if (m->total_size) {
- c += m->total_size;
+ update_size = m->total_size;
} else {
-#if !defined(__ROMCC__)
+ #if !defined(__ROMCC__)
printk(BIOS_WARNING, "Microcode has no valid size field!\n");
+ #endif
+ update_size = 2048;
+ }
+
+ /* Checkpoint 1: The microcode update falls within CBFS */
+ if(update_size > microcode_len) {
+#if !defined(__ROMCC__)
+ printk(BIOS_WARNING, "Microcode header corrupted!\n");
#endif
- c += 2048;
+ break;
}
+
+ if ((m->sig == sig) && (m->pf & pf))
+ return m;
+
+ microcode_updates += update_size;
+ microcode_len -= update_size;
}
/* ROMCC doesn't like NULL. */