ami: skip to next AMIBIOSC header if there's a AMINCBLK

The HP 2133 BIOS (AMI 0800) contains three different "AMIBIOSC" strings in the
file with the middle one being the correct one. The first one is from the main
BIOS image and can be identified by immediately being followed by an "AMINCBLK"
header. Skip it.

Change-Id: I21588fc9d5e2d636d0cba163192ef4aabe3789a1
Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
Reviewed-on: https://review.coreboot.org/20785
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
diff --git a/ami.c b/ami.c
index 65bebb1..2152160 100644
--- a/ami.c
+++ b/ami.c
@@ -19,6 +19,8 @@
  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define _GNU_SOURCE
+
 #include <stdio.h>
 #include <inttypes.h>
 #include <errno.h>
@@ -26,6 +28,7 @@
 #include <sys/mman.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <string.h>
 
 #include "bios_extract.h"
 #include "compat.h"
@@ -162,8 +165,23 @@
 		return FALSE;
 	}
 
-	/* now the individual modules */
-	abc = (struct abc *)(BIOSImage + ABCOffset);
+	if (ABCOffset + sizeof (struct abc) < BIOSLength) {
+		abc = (struct abc *)(BIOSImage + ABCOffset);
+		if (memcmp (abc->Version, "AMIN", 4) == 0) {
+			/* Skip to next one if immediately followed by "AMINCBLK"
+			 * header in place of a version number. */
+			abc = (struct abc *)memmem (BIOSImage + ABCOffset + 1,
+				BIOSLength - ABCOffset - 1 - sizeof (struct abc),
+				"AMIBIOSC", 8);
+		}
+	} else
+		abc = NULL;
+
+	if (!abc) {
+		fprintf(stderr,
+			"Error: short read after AMIBIOSC signature.\n");
+		return FALSE;
+	}
 
 	/* Get Date */
 	memcpy(Date, BIOSImage + BIOSLength - 11, 8);