efi.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:18k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * Extensible Firmware Interface
  3.  *
  4.  * Based on Extensible Firmware Interface Specification version 0.9 April 30, 1999
  5.  *
  6.  * Copyright (C) 1999 VA Linux Systems
  7.  * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
  8.  * Copyright (C) 1999-2002 Hewlett-Packard Co.
  9.  * David Mosberger-Tang <davidm@hpl.hp.com>
  10.  * Stephane Eranian <eranian@hpl.hp.com>
  11.  *
  12.  * All EFI Runtime Services are not implemented yet as EFI only
  13.  * supports physical mode addressing on SoftSDV. This is to be fixed
  14.  * in a future version.  --drummond 1999-07-20
  15.  *
  16.  * Implemented EFI runtime services and virtual mode calls.  --davidm
  17.  *
  18.  * Goutham Rao: <goutham.rao@intel.com>
  19.  * Skip non-WB memory and ignore empty memory ranges.
  20.  */
  21. #include <linux/config.h>
  22. #include <linux/kernel.h>
  23. #include <linux/init.h>
  24. #include <linux/types.h>
  25. #include <linux/time.h>
  26. #include <linux/proc_fs.h>
  27. #include <linux/efi.h>
  28. #include <asm/io.h>
  29. #include <asm/kregs.h>
  30. #include <asm/pgtable.h>
  31. #include <asm/processor.h>
  32. #define EFI_DEBUG 0
  33. extern efi_status_t efi_call_phys (void *, ...);
  34. struct efi efi;
  35. static efi_runtime_services_t *runtime;
  36. /*
  37.  * efi_dir is allocated here, but the directory isn't created
  38.  * here, as proc_mkdir() doesn't work this early in the bootup
  39.  * process.  Therefore, each module, like efivars, must test for
  40.  *    if (!efi_dir)  efi_dir = proc_mkdir("efi", NULL);
  41.  * prior to creating their own entries under /proc/efi.
  42.  */
  43. #ifdef CONFIG_PROC_FS
  44. struct proc_dir_entry *efi_dir = NULL;
  45. #endif
  46. static unsigned long mem_limit = ~0UL;
  47. static efi_status_t
  48. phys_get_time (efi_time_t *tm, efi_time_cap_t *tc)
  49. {
  50. return efi_call_phys(__va(runtime->get_time), __pa(tm), __pa(tc));
  51. }
  52. static efi_status_t
  53. phys_set_time (efi_time_t *tm)
  54. {
  55. return efi_call_phys(__va(runtime->set_time), __pa(tm));
  56. }
  57. static efi_status_t
  58. phys_get_wakeup_time (efi_bool_t *enabled, efi_bool_t *pending, efi_time_t *tm)
  59. {
  60. return efi_call_phys(__va(runtime->get_wakeup_time), __pa(enabled), __pa(pending),
  61.      __pa(tm));
  62. }
  63. static efi_status_t
  64. phys_set_wakeup_time (efi_bool_t enabled, efi_time_t *tm)
  65. {
  66. return efi_call_phys(__va(runtime->set_wakeup_time), enabled, __pa(tm));
  67. }
  68. static efi_status_t
  69. phys_get_variable (efi_char16_t *name, efi_guid_t *vendor, u32 *attr,
  70.    unsigned long *data_size, void *data)
  71. {
  72. return efi_call_phys(__va(runtime->get_variable), __pa(name), __pa(vendor), __pa(attr),
  73.      __pa(data_size), __pa(data));
  74. }
  75. static efi_status_t
  76. phys_get_next_variable (unsigned long *name_size, efi_char16_t *name, efi_guid_t *vendor)
  77. {
  78. return efi_call_phys(__va(runtime->get_next_variable), __pa(name_size), __pa(name),
  79.      __pa(vendor));
  80. }
  81. static efi_status_t
  82. phys_set_variable (efi_char16_t *name, efi_guid_t *vendor, u32 attr,
  83.    unsigned long data_size, void *data)
  84. {
  85. return efi_call_phys(__va(runtime->set_variable), __pa(name), __pa(vendor), attr,
  86.      data_size, __pa(data));
  87. }
  88. static efi_status_t
  89. phys_get_next_high_mono_count (u64 *count)
  90. {
  91. return efi_call_phys(__va(runtime->get_next_high_mono_count), __pa(count));
  92. }
  93. static void
  94. phys_reset_system (int reset_type, efi_status_t status,
  95.    unsigned long data_size, efi_char16_t *data)
  96. {
  97. efi_call_phys(__va(runtime->reset_system), status, data_size, __pa(data));
  98. }
  99. void
  100. efi_gettimeofday (struct timeval *tv)
  101. {
  102. efi_time_t tm;
  103. memset(tv, 0, sizeof(tv));
  104. if ((*efi.get_time)(&tm, 0) != EFI_SUCCESS)
  105. return;
  106. tv->tv_sec = mktime(tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second);
  107. tv->tv_usec = tm.nanosecond / 1000;
  108. }
  109. static int
  110. is_available_memory (efi_memory_desc_t *md)
  111. {
  112. if (!(md->attribute & EFI_MEMORY_WB))
  113. return 0;
  114. switch (md->type) {
  115.       case EFI_LOADER_CODE:
  116.       case EFI_LOADER_DATA:
  117.       case EFI_BOOT_SERVICES_CODE:
  118.       case EFI_BOOT_SERVICES_DATA:
  119.       case EFI_CONVENTIONAL_MEMORY:
  120. return 1;
  121. }
  122. return 0;
  123. }
  124. /*
  125.  * Trim descriptor MD so its starts at address START_ADDR.  If the descriptor covers
  126.  * memory that is normally available to the kernel, issue a warning that some memory
  127.  * is being ignored.
  128.  */
  129. static void
  130. trim_bottom (efi_memory_desc_t *md, u64 start_addr)
  131. {
  132. u64 num_skipped_pages;
  133. if (md->phys_addr >= start_addr || !md->num_pages)
  134. return;
  135. num_skipped_pages = (start_addr - md->phys_addr) >> EFI_PAGE_SHIFT;
  136. if (num_skipped_pages > md->num_pages)
  137. num_skipped_pages = md->num_pages;
  138. if (is_available_memory(md))
  139. printk(KERN_NOTICE "efi.%s: ignoring %luKB of memory at 0x%lx due to granule hole "
  140.        "at 0x%lxn", __FUNCTION__,
  141.        (num_skipped_pages << EFI_PAGE_SHIFT) >> 10,
  142.        md->phys_addr, start_addr - IA64_GRANULE_SIZE);
  143. /*
  144.  * NOTE: Don't set md->phys_addr to START_ADDR because that could cause the memory
  145.  * descriptor list to become unsorted.  In such a case, md->num_pages will be
  146.  * zero, so the Right Thing will happen.
  147.  */
  148. md->phys_addr += num_skipped_pages << EFI_PAGE_SHIFT;
  149. md->num_pages -= num_skipped_pages;
  150. }
  151. static void
  152. trim_top (efi_memory_desc_t *md, u64 end_addr)
  153. {
  154. u64 num_dropped_pages, md_end_addr;
  155. md_end_addr = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
  156. if (md_end_addr <= end_addr || !md->num_pages)
  157. return;
  158. num_dropped_pages = (md_end_addr - end_addr) >> EFI_PAGE_SHIFT;
  159. if (num_dropped_pages > md->num_pages)
  160. num_dropped_pages = md->num_pages;
  161. if (is_available_memory(md))
  162. printk(KERN_NOTICE "efi.%s: ignoring %luKB of memory at 0x%lx due to granule hole "
  163.        "at 0x%lxn", __FUNCTION__,
  164.        (num_dropped_pages << EFI_PAGE_SHIFT) >> 10,
  165.        md->phys_addr, end_addr);
  166. md->num_pages -= num_dropped_pages;
  167. }
  168. /*
  169.  * Walks the EFI memory map and calls CALLBACK once for each EFI memory descriptor that
  170.  * has memory that is available for OS use.
  171.  */
  172. void
  173. efi_memmap_walk (efi_freemem_callback_t callback, void *arg)
  174. {
  175. int prev_valid = 0;
  176. struct range {
  177. u64 start;
  178. u64 end;
  179. } prev, curr;
  180. void *efi_map_start, *efi_map_end, *p, *q;
  181. efi_memory_desc_t *md, *check_md;
  182. u64 efi_desc_size, start, end, granule_addr, first_non_wb_addr = 0;
  183. efi_map_start = __va(ia64_boot_param->efi_memmap);
  184. efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
  185. efi_desc_size = ia64_boot_param->efi_memdesc_size;
  186. for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
  187. md = p;
  188. /* skip over non-WB memory descriptors; that's all we're interested in... */
  189. if (!(md->attribute & EFI_MEMORY_WB))
  190. continue;
  191. if (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) > first_non_wb_addr) {
  192. /*
  193.  * Search for the next run of contiguous WB memory.  Start search
  194.  * at first granule boundary covered by md.
  195.  */
  196. granule_addr = ((md->phys_addr + IA64_GRANULE_SIZE - 1)
  197. & -IA64_GRANULE_SIZE);
  198. first_non_wb_addr = granule_addr;
  199. for (q = p; q < efi_map_end; q += efi_desc_size) {
  200. check_md = q;
  201. if (check_md->attribute & EFI_MEMORY_WB)
  202. trim_bottom(md, granule_addr);
  203. if (check_md->phys_addr < granule_addr)
  204. continue;
  205. if (!(check_md->attribute & EFI_MEMORY_WB))
  206. break; /* hit a non-WB region; stop search */
  207. if (check_md->phys_addr != first_non_wb_addr)
  208. break; /* hit a memory hole; stop search */
  209. first_non_wb_addr += check_md->num_pages << EFI_PAGE_SHIFT;
  210. }
  211. /* round it down to the previous granule-boundary: */
  212. first_non_wb_addr &= -IA64_GRANULE_SIZE;
  213. if (!(first_non_wb_addr > granule_addr))
  214. continue; /* couldn't find enough contiguous memory */
  215. }
  216. /* BUG_ON((md->phys_addr >> IA64_GRANULE_SHIFT) < first_non_wb_addr); */
  217. trim_top(md, first_non_wb_addr);
  218. if (is_available_memory(md)) {
  219. if (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) > mem_limit) {
  220. if (md->phys_addr > mem_limit)
  221. continue;
  222. md->num_pages = (mem_limit - md->phys_addr) >> EFI_PAGE_SHIFT;
  223. }
  224. if (md->num_pages == 0)
  225. continue;
  226. curr.start = PAGE_OFFSET + md->phys_addr;
  227. curr.end   = curr.start + (md->num_pages << EFI_PAGE_SHIFT);
  228. if (!prev_valid) {
  229. prev = curr;
  230. prev_valid = 1;
  231. } else {
  232. if (curr.start < prev.start)
  233. printk("Oops: EFI memory table not ordered!n");
  234. if (prev.end == curr.start) {
  235. /* merge two consecutive memory ranges */
  236. prev.end = curr.end;
  237. } else {
  238. start = PAGE_ALIGN(prev.start);
  239. end = prev.end & PAGE_MASK;
  240. if ((end > start) && (*callback)(start, end, arg) < 0)
  241. return;
  242. prev = curr;
  243. }
  244. }
  245. }
  246. }
  247. if (prev_valid) {
  248. start = PAGE_ALIGN(prev.start);
  249. end = prev.end & PAGE_MASK;
  250. if (end > start)
  251. (*callback)(start, end, arg);
  252. }
  253. }
  254. /*
  255.  * Look for the PAL_CODE region reported by EFI and maps it using an
  256.  * ITR to enable safe PAL calls in virtual mode.  See IA-64 Processor
  257.  * Abstraction Layer chapter 11 in ADAG
  258.  */
  259. void
  260. efi_map_pal_code (void)
  261. {
  262. void *efi_map_start, *efi_map_end, *p;
  263. efi_memory_desc_t *md;
  264. u64 efi_desc_size;
  265. int pal_code_count = 0;
  266. u64 mask, psr;
  267. u64 vaddr;
  268. efi_map_start = __va(ia64_boot_param->efi_memmap);
  269. efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
  270. efi_desc_size = ia64_boot_param->efi_memdesc_size;
  271. for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
  272. md = p;
  273. if (md->type != EFI_PAL_CODE)
  274. continue;
  275. if (++pal_code_count > 1) {
  276. printk(KERN_ERR "Too many EFI Pal Code memory ranges, dropped @ %lxn",
  277.        md->phys_addr);
  278. continue;
  279. }
  280. /*
  281.  * The only ITLB entry in region 7 that is used is the one installed by
  282.  * __start().  That entry covers a 64MB range.
  283.  */
  284. mask  = ~((1 << KERNEL_TR_PAGE_SHIFT) - 1);
  285. vaddr = PAGE_OFFSET + md->phys_addr;
  286. /*
  287.  * We must check that the PAL mapping won't overlap with the kernel
  288.  * mapping.
  289.  *
  290.  * PAL code is guaranteed to be aligned on a power of 2 between 4k and
  291.  * 256KB and that only one ITR is needed to map it. This implies that the
  292.  * PAL code is always aligned on its size, i.e., the closest matching page
  293.  * size supported by the TLB. Therefore PAL code is guaranteed never to
  294.  * cross a 64MB unless it is bigger than 64MB (very unlikely!).  So for
  295.  * now the following test is enough to determine whether or not we need a
  296.  * dedicated ITR for the PAL code.
  297.  */
  298. if ((vaddr & mask) == (KERNEL_START & mask)) {
  299. printk("%s: no need to install ITR for PAL coden", __FUNCTION__);
  300. continue;
  301. }
  302. if (md->num_pages << EFI_PAGE_SHIFT > IA64_GRANULE_SIZE)
  303. panic("Woah!  PAL code size bigger than a granule!");
  304. mask  = ~((1 << IA64_GRANULE_SHIFT) - 1);
  305. printk("CPU %d: mapping PAL code [0x%lx-0x%lx) into [0x%lx-0x%lx)n",
  306.        smp_processor_id(), md->phys_addr,
  307.        md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT),
  308.        vaddr & mask, (vaddr & mask) + IA64_GRANULE_SIZE);
  309. /*
  310.  * Cannot write to CRx with PSR.ic=1
  311.  */
  312. psr = ia64_clear_ic();
  313. ia64_itr(0x1, IA64_TR_PALCODE, vaddr & mask,
  314.  pte_val(mk_pte_phys(md->phys_addr, PAGE_KERNEL)), IA64_GRANULE_SHIFT);
  315. ia64_set_psr(psr); /* restore psr */
  316. ia64_srlz_i();
  317. }
  318. }
  319. void __init
  320. efi_init (void)
  321. {
  322. void *efi_map_start, *efi_map_end;
  323. efi_config_table_t *config_tables;
  324. efi_char16_t *c16;
  325. u64 efi_desc_size;
  326. char *cp, *end, vendor[100] = "unknown";
  327. extern char saved_command_line[];
  328. int i;
  329. /* it's too early to be able to use the standard kernel command line support... */
  330. for (cp = saved_command_line; *cp; ) {
  331. if (memcmp(cp, "mem=", 4) == 0) {
  332. cp += 4;
  333. mem_limit = memparse(cp, &end) - 1;
  334. if (end != cp)
  335. break;
  336. cp = end;
  337. } else {
  338. while (*cp != ' ' && *cp)
  339. ++cp;
  340. while (*cp == ' ')
  341. ++cp;
  342. }
  343. }
  344. if (mem_limit != ~0UL)
  345. printk("Ignoring memory above %luMBn", mem_limit >> 20);
  346. efi.systab = __va(ia64_boot_param->efi_systab);
  347. /*
  348.  * Verify the EFI Table
  349.  */
  350. if (efi.systab == NULL)
  351. panic("Woah! Can't find EFI system table.n");
  352. if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
  353. panic("Woah! EFI system table signature incorrectn");
  354. if ((efi.systab->hdr.revision ^ EFI_SYSTEM_TABLE_REVISION) >> 16 != 0)
  355. printk("Warning: EFI system table major version mismatch: "
  356.        "got %d.%02d, expected %d.%02dn",
  357.        efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff,
  358.        EFI_SYSTEM_TABLE_REVISION >> 16, EFI_SYSTEM_TABLE_REVISION & 0xffff);
  359. config_tables = __va(efi.systab->tables);
  360. /* Show what we know for posterity */
  361. c16 = __va(efi.systab->fw_vendor);
  362. if (c16) {
  363. for (i = 0;i < sizeof(vendor) && *c16; ++i)
  364. vendor[i] = *c16++;
  365. vendor[i] = '';
  366. }
  367. printk("EFI v%u.%.02u by %s:",
  368.        efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, vendor);
  369. for (i = 0; i < efi.systab->nr_tables; i++) {
  370. if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) {
  371. efi.mps = __va(config_tables[i].table);
  372. printk(" MPS=0x%lx", config_tables[i].table);
  373. } else if (efi_guidcmp(config_tables[i].guid, ACPI_20_TABLE_GUID) == 0) {
  374. efi.acpi20 = __va(config_tables[i].table);
  375. printk(" ACPI 2.0=0x%lx", config_tables[i].table);
  376. } else if (efi_guidcmp(config_tables[i].guid, ACPI_TABLE_GUID) == 0) {
  377. efi.acpi = __va(config_tables[i].table);
  378. printk(" ACPI=0x%lx", config_tables[i].table);
  379. } else if (efi_guidcmp(config_tables[i].guid, SMBIOS_TABLE_GUID) == 0) {
  380. efi.smbios = __va(config_tables[i].table);
  381. printk(" SMBIOS=0x%lx", config_tables[i].table);
  382. } else if (efi_guidcmp(config_tables[i].guid, SAL_SYSTEM_TABLE_GUID) == 0) {
  383. efi.sal_systab = __va(config_tables[i].table);
  384. printk(" SALsystab=0x%lx", config_tables[i].table);
  385. } else if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) {
  386. efi.hcdp = __va(config_tables[i].table);
  387. printk(" HCDP=0x%lx", config_tables[i].table);
  388. }
  389. }
  390. printk("n");
  391. runtime = __va(efi.systab->runtime);
  392. efi.get_time = phys_get_time;
  393. efi.set_time = phys_set_time;
  394. efi.get_wakeup_time = phys_get_wakeup_time;
  395. efi.set_wakeup_time = phys_set_wakeup_time;
  396. efi.get_variable = phys_get_variable;
  397. efi.get_next_variable = phys_get_next_variable;
  398. efi.set_variable = phys_set_variable;
  399. efi.get_next_high_mono_count = phys_get_next_high_mono_count;
  400. efi.reset_system = phys_reset_system;
  401. efi_map_start = __va(ia64_boot_param->efi_memmap);
  402. efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
  403. efi_desc_size = ia64_boot_param->efi_memdesc_size;
  404. #if EFI_DEBUG
  405. /* print EFI memory map: */
  406. {
  407. efi_memory_desc_t *md;
  408. void *p;
  409. for (i = 0, p = efi_map_start; p < efi_map_end; ++i, p += efi_desc_size) {
  410. md = p;
  411. printk("mem%02u: type=%u, attr=0x%lx, range=[0x%016lx-0x%016lx) (%luMB)n",
  412.        i, md->type, md->attribute, md->phys_addr,
  413.        md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT),
  414.        md->num_pages >> (20 - EFI_PAGE_SHIFT));
  415. }
  416. }
  417. #endif
  418. efi_map_pal_code();
  419. efi_enter_virtual_mode();
  420. }
  421. void
  422. efi_enter_virtual_mode (void)
  423. {
  424. void *efi_map_start, *efi_map_end, *p;
  425. efi_memory_desc_t *md;
  426. efi_status_t status;
  427. u64 efi_desc_size;
  428. efi_map_start = __va(ia64_boot_param->efi_memmap);
  429. efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
  430. efi_desc_size = ia64_boot_param->efi_memdesc_size;
  431. for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
  432. md = p;
  433. if (md->attribute & EFI_MEMORY_RUNTIME) {
  434. /*
  435.  * Some descriptors have multiple bits set, so the order of
  436.  * the tests is relevant.
  437.  */
  438. if (md->attribute & EFI_MEMORY_WB) {
  439. md->virt_addr = (u64) __va(md->phys_addr);
  440. } else if (md->attribute & EFI_MEMORY_UC) {
  441. md->virt_addr = (u64) ioremap(md->phys_addr, 0);
  442. } else if (md->attribute & EFI_MEMORY_WC) {
  443. #if 0
  444. md->virt_addr = ia64_remap(md->phys_addr, (_PAGE_A | _PAGE_P
  445.    | _PAGE_D
  446.    | _PAGE_MA_WC
  447.    | _PAGE_PL_0
  448.    | _PAGE_AR_RW));
  449. #else
  450. printk("EFI_MEMORY_WC mappingn");
  451. md->virt_addr = (u64) ioremap(md->phys_addr, 0);
  452. #endif
  453. } else if (md->attribute & EFI_MEMORY_WT) {
  454. #if 0
  455. md->virt_addr = ia64_remap(md->phys_addr, (_PAGE_A | _PAGE_P
  456.    | _PAGE_D | _PAGE_MA_WT
  457.    | _PAGE_PL_0
  458.    | _PAGE_AR_RW));
  459. #else
  460. printk("EFI_MEMORY_WT mappingn");
  461. md->virt_addr = (u64) ioremap(md->phys_addr, 0);
  462. #endif
  463. }
  464. }
  465. }
  466. status = efi_call_phys(__va(runtime->set_virtual_address_map),
  467.        ia64_boot_param->efi_memmap_size,
  468.        efi_desc_size, ia64_boot_param->efi_memdesc_version,
  469.        ia64_boot_param->efi_memmap);
  470. if (status != EFI_SUCCESS) {
  471. printk("Warning: unable to switch EFI into virtual mode (status=%lu)n", status);
  472. return;
  473. }
  474. /*
  475.  * Now that EFI is in virtual mode, we arrange for EFI functions to be
  476.  * called directly:
  477.  */
  478. efi.get_time = __va(runtime->get_time);
  479. efi.set_time = __va(runtime->set_time);
  480. efi.get_wakeup_time = __va(runtime->get_wakeup_time);
  481. efi.set_wakeup_time = __va(runtime->set_wakeup_time);
  482. efi.get_variable = __va(runtime->get_variable);
  483. efi.get_next_variable = __va(runtime->get_next_variable);
  484. efi.set_variable = __va(runtime->set_variable);
  485. efi.get_next_high_mono_count = __va(runtime->get_next_high_mono_count);
  486. efi.reset_system = __va(runtime->reset_system);
  487. }
  488. /*
  489.  * Walk the EFI memory map looking for the I/O port range.  There can only be one entry of
  490.  * this type, other I/O port ranges should be described via ACPI.
  491.  */
  492. u64
  493. efi_get_iobase (void)
  494. {
  495. void *efi_map_start, *efi_map_end, *p;
  496. efi_memory_desc_t *md;
  497. u64 efi_desc_size;
  498. efi_map_start = __va(ia64_boot_param->efi_memmap);
  499. efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
  500. efi_desc_size = ia64_boot_param->efi_memdesc_size;
  501. for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
  502. md = p;
  503. if (md->type == EFI_MEMORY_MAPPED_IO_PORT_SPACE) {
  504. /* paranoia attribute checking */
  505. if (md->attribute == (EFI_MEMORY_UC | EFI_MEMORY_RUNTIME))
  506. return md->phys_addr;
  507. }
  508. }
  509. return 0;
  510. }
  511. u32
  512. efi_mem_type (unsigned long phys_addr)
  513. {
  514. void *efi_map_start, *efi_map_end, *p;
  515. efi_memory_desc_t *md;
  516. u64 efi_desc_size;
  517. efi_map_start = __va(ia64_boot_param->efi_memmap);
  518. efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
  519. efi_desc_size = ia64_boot_param->efi_memdesc_size;
  520. for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
  521. md = p;
  522. if ((md->phys_addr <= phys_addr) && (phys_addr <=
  523.     (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1)))
  524.  return md->type;
  525. }
  526. return 0;
  527. }
  528. u64
  529. efi_mem_attributes (unsigned long phys_addr)
  530. {
  531. void *efi_map_start, *efi_map_end, *p;
  532. efi_memory_desc_t *md;
  533. u64 efi_desc_size;
  534. efi_map_start = __va(ia64_boot_param->efi_memmap);
  535. efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
  536. efi_desc_size = ia64_boot_param->efi_memdesc_size;
  537. for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
  538. md = p;
  539. if ((md->phys_addr <= phys_addr) && (phys_addr <=
  540.     (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1)))
  541. return md->attribute;
  542. }
  543. return 0;
  544. }
  545. static void __exit
  546. efivars_exit (void)
  547. {
  548. #ifdef CONFIG_PROC_FS
  549.   remove_proc_entry(efi_dir->name, NULL);
  550. #endif
  551. }