/* * sfi_map_table() * * Return address of mapped table * Check for common case that we can re-use mapping to SYST, * which requires syst_pa, syst_va to be initialized. */ struct sfi_table_header *sfi_map_table(u64 pa) { struct sfi_table_header *th; u32 length; pr_emerg("Entering sfi_map_table, pa = %llx\n", pa); if (!TABLE_ON_PAGE(syst_pa, pa, sizeof(struct sfi_table_header))) th = sfi_map_memory(pa, sizeof(struct sfi_table_header)); else th = (void *)syst_va + (pa - syst_pa); pr_emerg("sfi_map_table, th = %llx\n", (u64)th); /* If table fits on same page as its header, we are done */ if (TABLE_ON_PAGE(th, th, th->len)) return th; /* Entire table does not fit on same page as SYST */ length = th->len; if (!TABLE_ON_PAGE(syst_pa, pa, sizeof(struct sfi_table_header))) sfi_unmap_memory(th, sizeof(struct sfi_table_header)); return sfi_map_memory(pa, length); }
struct sfi_table_header *sfi_map_table(u64 pa) { struct sfi_table_header *th; u32 length; if (!TABLE_ON_PAGE(syst_pa, pa, sizeof(struct sfi_table_header))) th = sfi_map_memory(pa, sizeof(struct sfi_table_header)); else th = (void *)syst_va + (pa - syst_pa); if (TABLE_ON_PAGE(th, th, th->len)) return th; length = th->len; if (!TABLE_ON_PAGE(syst_pa, pa, sizeof(struct sfi_table_header))) sfi_unmap_memory(th, sizeof(struct sfi_table_header)); return sfi_map_memory(pa, length); }
void __init sfi_init_late(void) { int length; if (sfi_disabled) return; length = syst_va->header.len; sfi_unmap_memory(syst_va, sizeof(struct sfi_table_simple)); /* Use memremap now after it is ready */ sfi_use_memremap = 1; syst_va = sfi_map_memory(syst_pa, length); sfi_acpi_init(); }
/* * The OS finds the System Table by searching 16-byte boundaries between * physical address 0x000E0000 and 0x000FFFFF. The OS shall search this region * starting at the low address and shall stop searching when the 1st valid SFI * System Table is found. * * success: set syst_pa, return 0 * fail: return -1 */ static __init int sfi_find_syst(void) { unsigned long offset, len; void *start; len = SFI_SYST_SEARCH_END - SFI_SYST_SEARCH_BEGIN; start = sfi_map_memory(SFI_SYST_SEARCH_BEGIN, len); if (!start) return -1; for (offset = 0; offset < len; offset += 16) { struct sfi_table_header *syst_hdr; syst_hdr = start + offset; if (strncmp(syst_hdr->sig, SFI_SIG_SYST, SFI_SIGNATURE_SIZE)) continue; if (syst_hdr->len > PAGE_SIZE) continue; sfi_print_table_header(SFI_SYST_SEARCH_BEGIN + offset, syst_hdr); if (sfi_verify_table(syst_hdr)) continue; /* * Enforce SFI spec mandate that SYST reside within a page. */ if (!ON_SAME_PAGE(syst_pa, syst_pa + syst_hdr->len)) { pr_info("SYST 0x%llx + 0x%x crosses page\n", syst_pa, syst_hdr->len); continue; } /* Success */ syst_pa = SFI_SYST_SEARCH_BEGIN + offset; sfi_unmap_memory(start, len); return 0; } sfi_unmap_memory(start, len); return -1; }
/* * sfi_parse_syst() * Checksum all the tables in SYST and print their headers * * success: set syst_va, return 0 */ static int __init sfi_parse_syst(void) { struct sfi_table_key key = SFI_ANY_KEY; int tbl_cnt, i; void *ret; syst_va = sfi_map_memory(syst_pa, sizeof(struct sfi_table_simple)); if (!syst_va) return -ENOMEM; tbl_cnt = SFI_GET_NUM_ENTRIES(syst_va, u64); for (i = 0; i < tbl_cnt; i++) { ret = sfi_check_table(syst_va->pentry[i], &key); if (IS_ERR(ret)) return PTR_ERR(ret); } return 0; }
void __init sfi_init_late(void) { int length; if (sfi_disabled) return; length = syst_va->header.len; sfi_unmap_memory(syst_va, sizeof(struct sfi_table_simple)); /* Use ioremap now after it is ready */ sfi_use_ioremap = 1; #ifdef CONFIG_X86_EARLYMIC /* E820 does not mark page reserved */ memblock_reserve(0x92000, PAGE_SIZE); /* needed for ioremap */ SetPageReserved(pfn_to_page(0x92)); #endif syst_va = sfi_map_memory(syst_pa, length); sfi_acpi_init(); }