summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark F. Brown <mark.f.brown@intel.com>2011-09-07 18:09:37 -0400
committerPatrick Tjin <pattjin@google.com>2014-07-21 20:22:40 -0700
commitafcd466aef22166c77f3f41414167972d44acd0b (patch)
treedcdf11edf39595d42292f75a4a9f7b8db945edaa
parent90847a8a794a6eedef1f61daab5a9e3afde33c5a (diff)
downloadbootstub-afcd466aef22166c77f3f41414167972d44acd0b.tar.gz
SFI: Fixed MMAP search routine
BZ: 114933 Needs to search for MMAP via SYST table Added SFI table verification Optimized table search: * Search for SYST on 16-byte boundary * Table signature match via magic number rather than strcmp Change-Id: Ic1e32eb7622ac1839ceb22e1315df50709df485a Signed-off-by: Mark F. Brown <mark.f.brown@intel.com> Reviewed-by: Jim A. Pelner <jim.a.pelner@intel.com> Reviewed-on: http://android.intel.com:8080/112532 Reviewed-by: Fourdan, Olivier <olivier.fourdan@intel.com> Tested-by: Fourdan, Olivier <olivier.fourdan@intel.com> Reviewed-by: Fert, Laurent <laurent.fert@intel.com> Reviewed-by: cactus <cactus@intel.com> Tested-by: cactus <cactus@intel.com>
-rw-r--r--sfi.c70
-rw-r--r--sfi.h13
2 files changed, 71 insertions, 12 deletions
diff --git a/sfi.c b/sfi.c
index f5e5656..1f88d71 100644
--- a/sfi.c
+++ b/sfi.c
@@ -25,19 +25,67 @@
#define SFI_BASE_ADDR 0x000E0000
#define SFI_LENGTH 0x00020000
+#define SFI_TABLE_LENGTH 16
-static unsigned long sfi_search_mmap(unsigned long start, int len)
+static int sfi_table_check(struct sfi_table_header *sbh)
{
- unsigned long i = 0;
- char *pchar = (char *)start;
-
- for (i = 0; i < len; i++, pchar++) {
- if (pchar[0] == 'M'
- && pchar[1] == 'M'
- && pchar[2] == 'A'
- && pchar[3] == 'P')
- return start + i;
+ char chksum = 0;
+ char *pos = (char *)sbh;
+ int i;
+
+ if (sbh->length < SFI_TABLE_LENGTH)
+ return -1;
+
+ if (sbh->length > SFI_LENGTH)
+ return -1;
+
+ for (i = 0; i < sbh->length; i++)
+ chksum += *pos++;
+
+ if (chksum)
+ bs_printk("sfi: Invalid checksum\n");
+
+ /* checksum is ok if zero */
+ return chksum;
+}
+
+static unsigned long sfi_search_mmap(void)
+{
+ u32 i = 0;
+ u32 *pos = (u32 *)SFI_BASE_ADDR;
+ u32 *end = (u32 *)(SFI_BASE_ADDR + SFI_LENGTH);
+ struct sfi_table_header *sbh;
+ struct sfi_table *sb;
+ u32 sys_entry_cnt = 0;
+
+ /* Find SYST table */
+ for (; pos < end; pos += 4) {
+ if (*pos == SFI_SYST_MAGIC) {
+ if (!sfi_table_check((struct sfi_table_header *)pos))
+ break;
+ }
+ }
+
+ if (pos >= end) {
+ bs_printk("Bootstub: failed to locate SFI SYST table\n");
+ return 0;
}
+
+ /* map table pointers */
+ sb = (struct sfi_table *)pos;
+ sbh = (struct sfi_table_header *)sb;
+
+ sys_entry_cnt = (sbh->length - sizeof(struct sfi_table_header)) >> 3;
+
+ /* Search through each SYST entry for MMAP table */
+ for (i = 0; i < sys_entry_cnt; i++) {
+ sbh = (struct sfi_table_header *)sb->entry[i].low;
+ if (*(u32 *)sbh->signature == SFI_MMAP_MAGIC) {
+ if (!sfi_table_check((struct sfi_table_header *)sbh))
+ return (unsigned long) sbh;
+ }
+ }
+
return 0;
}
@@ -52,7 +100,7 @@ void sfi_setup_e820(struct boot_params *bp)
total = 0;
/* search for sfi mmap table */
- sb = (struct sfi_table *)sfi_search_mmap(SFI_BASE_ADDR, SFI_LENGTH);
+ sb = (struct sfi_table *)sfi_search_mmap();
if (!sb) {
bs_printk("Bootstub: failed to locate SFI MMAP table\n");
return;
diff --git a/sfi.h b/sfi.h
index 019cc96..21e5d1a 100644
--- a/sfi.h
+++ b/sfi.h
@@ -37,9 +37,17 @@ struct sfi_table_header {
char oem_table_id[8];
}__attribute__((packed));
+struct __sfi_quad_word {
+ u32 low;
+ u32 high;
+};
+
struct sfi_table {
struct sfi_table_header header;
- u64 pentry[1];
+ union {
+ u64 pentry[1];
+ struct __sfi_quad_word entry[1];
+ };
}__attribute__((packed));
#define SFI_TBL_HEADER_LEN 24
@@ -54,5 +62,8 @@ struct sfi_table {
#define E820_NVS 4
#define E820_UNUSABLE 5
+#define SFI_SYST_MAGIC 0x54535953 /* SYST */
+#define SFI_MMAP_MAGIC 0x50414d4d /* MMAP */
+
extern void sfi_setup_e820(struct boot_params *bp);
#endif /* _SFI_H */