/*1* Extensible Firmware Interface2*3* Based on Extensible Firmware Interface Specification version 1.04*5* Copyright (C) 1999 VA Linux Systems6* Copyright (C) 1999 Walt Drummond <[email protected]>7* Copyright (C) 1999-2002 Hewlett-Packard Co.8* David Mosberger-Tang <[email protected]>9* Stephane Eranian <[email protected]>10*11* All EFI Runtime Services are not implemented yet as EFI only12* supports physical mode addressing on SoftSDV. This is to be fixed13* in a future version. --drummond 1999-07-2014*15* Implemented EFI runtime services and virtual mode calls. --davidm16*17* Goutham Rao: <[email protected]>18* Skip non-WB memory and ignore empty memory ranges.19*/2021#include <linux/kernel.h>22#include <linux/types.h>23#include <linux/ioport.h>24#include <linux/efi.h>2526#include <asm/io.h>27#include <asm/page.h>28#include <asm/pgtable.h>29#include <asm/tlbflush.h>30#include <asm/efi.h>3132/*33* To make EFI call EFI runtime service in physical addressing mode we need34* prelog/epilog before/after the invocation to disable interrupt, to35* claim EFI runtime service handler exclusively and to duplicate a memory in36* low memory space say 0 - 3G.37*/3839static unsigned long efi_rt_eflags;40static pgd_t efi_bak_pg_dir_pointer[2];4142void efi_call_phys_prelog(void)43{44unsigned long cr4;45unsigned long temp;46struct desc_ptr gdt_descr;4748local_irq_save(efi_rt_eflags);4950/*51* If I don't have PAE, I should just duplicate two entries in page52* directory. If I have PAE, I just need to duplicate one entry in53* page directory.54*/55cr4 = read_cr4_safe();5657if (cr4 & X86_CR4_PAE) {58efi_bak_pg_dir_pointer[0].pgd =59swapper_pg_dir[pgd_index(0)].pgd;60swapper_pg_dir[0].pgd =61swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd;62} else {63efi_bak_pg_dir_pointer[0].pgd =64swapper_pg_dir[pgd_index(0)].pgd;65efi_bak_pg_dir_pointer[1].pgd =66swapper_pg_dir[pgd_index(0x400000)].pgd;67swapper_pg_dir[pgd_index(0)].pgd =68swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd;69temp = PAGE_OFFSET + 0x400000;70swapper_pg_dir[pgd_index(0x400000)].pgd =71swapper_pg_dir[pgd_index(temp)].pgd;72}7374/*75* After the lock is released, the original page table is restored.76*/77__flush_tlb_all();7879gdt_descr.address = __pa(get_cpu_gdt_table(0));80gdt_descr.size = GDT_SIZE - 1;81load_gdt(&gdt_descr);82}8384void efi_call_phys_epilog(void)85{86unsigned long cr4;87struct desc_ptr gdt_descr;8889gdt_descr.address = (unsigned long)get_cpu_gdt_table(0);90gdt_descr.size = GDT_SIZE - 1;91load_gdt(&gdt_descr);9293cr4 = read_cr4_safe();9495if (cr4 & X86_CR4_PAE) {96swapper_pg_dir[pgd_index(0)].pgd =97efi_bak_pg_dir_pointer[0].pgd;98} else {99swapper_pg_dir[pgd_index(0)].pgd =100efi_bak_pg_dir_pointer[0].pgd;101swapper_pg_dir[pgd_index(0x400000)].pgd =102efi_bak_pg_dir_pointer[1].pgd;103}104105/*106* After the lock is released, the original page table is restored.107*/108__flush_tlb_all();109110local_irq_restore(efi_rt_eflags);111}112113114