diff options
author | Mark F. Brown <mark.f.brown@intel.com> | 2011-09-07 18:09:37 -0400 |
---|---|---|
committer | Patrick Tjin <pattjin@google.com> | 2014-07-21 20:22:40 -0700 |
commit | afcd466aef22166c77f3f41414167972d44acd0b (patch) | |
tree | dcdf11edf39595d42292f75a4a9f7b8db945edaa | |
parent | 90847a8a794a6eedef1f61daab5a9e3afde33c5a (diff) | |
download | bootstub-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.c | 70 | ||||
-rw-r--r-- | sfi.h | 13 |
2 files changed, 71 insertions, 12 deletions
@@ -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; @@ -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 */ |