123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- // SPDX-License-Identifier: GPL-2.0+
- /*
- * Copyright (c) 2017 Intel Corporation
- */
- #include <common.h>
- #include <asm/e820.h>
- #include <asm/global_data.h>
- #include <asm/sfi.h>
- DECLARE_GLOBAL_DATA_PTR;
- /*
- * SFI tables are part of the first stage bootloader.
- *
- * U-Boot finds the System Table by searching 16-byte boundaries between
- * physical address 0x000E0000 and 0x000FFFFF. U-Boot shall search this region
- * starting at the low address and shall stop searching when the 1st valid SFI
- * System Table is found.
- */
- #define SFI_BASE_ADDR 0x000E0000
- #define SFI_LENGTH 0x00020000
- #define SFI_TABLE_LENGTH 16
- static int sfi_table_check(struct sfi_table_header *sbh)
- {
- char chksum = 0;
- char *pos = (char *)sbh;
- u32 i;
- if (sbh->len < SFI_TABLE_LENGTH)
- return -ENXIO;
- if (sbh->len > SFI_LENGTH)
- return -ENXIO;
- for (i = 0; i < sbh->len; i++)
- chksum += *pos++;
- if (chksum)
- pr_err("sfi: Invalid checksum\n");
- /* Checksum is OK if zero */
- return chksum ? -EILSEQ : 0;
- }
- static int sfi_table_is_type(struct sfi_table_header *sbh, const char *signature)
- {
- return !strncmp(sbh->sig, signature, SFI_SIGNATURE_SIZE) &&
- !sfi_table_check(sbh);
- }
- static struct sfi_table_simple *sfi_get_table_by_sig(unsigned long addr,
- const char *signature)
- {
- struct sfi_table_simple *sb;
- u32 i;
- for (i = 0; i < SFI_LENGTH; i += SFI_TABLE_LENGTH) {
- sb = (struct sfi_table_simple *)(addr + i);
- if (sfi_table_is_type(&sb->header, signature))
- return sb;
- }
- return NULL;
- }
- static struct sfi_table_simple *sfi_search_mmap(void)
- {
- struct sfi_table_header *sbh;
- struct sfi_table_simple *sb;
- u32 sys_entry_cnt;
- u32 i;
- /* Find SYST table */
- sb = sfi_get_table_by_sig(SFI_BASE_ADDR, SFI_SIG_SYST);
- if (!sb) {
- pr_err("sfi: failed to locate SYST table\n");
- return NULL;
- }
- sys_entry_cnt = (sb->header.len - sizeof(*sbh)) / 8;
- /* Search through each SYST entry for MMAP table */
- for (i = 0; i < sys_entry_cnt; i++) {
- sbh = (struct sfi_table_header *)(unsigned long)sb->pentry[i];
- if (sfi_table_is_type(sbh, SFI_SIG_MMAP))
- return (struct sfi_table_simple *)sbh;
- }
- pr_err("sfi: failed to locate SFI MMAP table\n");
- return NULL;
- }
- #define sfi_for_each_mentry(i, sb, mentry) \
- for (i = 0, mentry = (struct sfi_mem_entry *)sb->pentry; \
- i < SFI_GET_NUM_ENTRIES(sb, struct sfi_mem_entry); \
- i++, mentry++) \
- static unsigned int sfi_setup_e820(unsigned int max_entries,
- struct e820_entry *entries)
- {
- struct sfi_table_simple *sb;
- struct sfi_mem_entry *mentry;
- unsigned long long start, end, size;
- int type, total = 0;
- u32 i;
- sb = sfi_search_mmap();
- if (!sb)
- return 0;
- sfi_for_each_mentry(i, sb, mentry) {
- start = mentry->phys_start;
- size = mentry->pages << 12;
- end = start + size;
- if (start > end)
- continue;
- /* translate SFI mmap type to E820 map type */
- switch (mentry->type) {
- case SFI_MEM_CONV:
- type = E820_RAM;
- break;
- case SFI_MEM_UNUSABLE:
- case SFI_RUNTIME_SERVICE_DATA:
- continue;
- default:
- type = E820_RESERVED;
- }
- if (total == E820MAX)
- break;
- entries[total].addr = start;
- entries[total].size = size;
- entries[total].type = type;
- total++;
- }
- return total;
- }
- static int sfi_get_bank_size(void)
- {
- struct sfi_table_simple *sb;
- struct sfi_mem_entry *mentry;
- int bank = 0;
- u32 i;
- sb = sfi_search_mmap();
- if (!sb)
- return 0;
- sfi_for_each_mentry(i, sb, mentry) {
- if (mentry->type != SFI_MEM_CONV)
- continue;
- gd->bd->bi_dram[bank].start = mentry->phys_start;
- gd->bd->bi_dram[bank].size = mentry->pages << 12;
- bank++;
- }
- return bank;
- }
- static phys_size_t sfi_get_ram_size(void)
- {
- struct sfi_table_simple *sb;
- struct sfi_mem_entry *mentry;
- phys_size_t ram = 0;
- u32 i;
- sb = sfi_search_mmap();
- if (!sb)
- return 0;
- sfi_for_each_mentry(i, sb, mentry) {
- if (mentry->type != SFI_MEM_CONV)
- continue;
- ram += mentry->pages << 12;
- }
- debug("sfi: RAM size %llu\n", ram);
- return ram;
- }
- unsigned int install_e820_map(unsigned int max_entries,
- struct e820_entry *entries)
- {
- return sfi_setup_e820(max_entries, entries);
- }
- int dram_init_banksize(void)
- {
- sfi_get_bank_size();
- return 0;
- }
- int dram_init(void)
- {
- gd->ram_size = sfi_get_ram_size();
- return 0;
- }
|