1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
17
18#include <linux/kobject.h>
19#include <linux/module.h>
20#include <linux/init.h>
21#include <linux/device.h>
22#include <linux/efi.h>
23#include <linux/of.h>
24#include <linux/of_fdt.h>
25#include <linux/io.h>
26#include <linux/kexec.h>
27#include <linux/platform_device.h>
28#include <linux/random.h>
29#include <linux/reboot.h>
30#include <linux/slab.h>
31#include <linux/acpi.h>
32#include <linux/ucs2_string.h>
33#include <linux/memblock.h>
34
35#include <asm/early_ioremap.h>
36
37struct efi __read_mostly efi = {
38 .mps = EFI_INVALID_TABLE_ADDR,
39 .acpi = EFI_INVALID_TABLE_ADDR,
40 .acpi20 = EFI_INVALID_TABLE_ADDR,
41 .smbios = EFI_INVALID_TABLE_ADDR,
42 .smbios3 = EFI_INVALID_TABLE_ADDR,
43 .sal_systab = EFI_INVALID_TABLE_ADDR,
44 .boot_info = EFI_INVALID_TABLE_ADDR,
45 .hcdp = EFI_INVALID_TABLE_ADDR,
46 .uga = EFI_INVALID_TABLE_ADDR,
47 .uv_systab = EFI_INVALID_TABLE_ADDR,
48 .fw_vendor = EFI_INVALID_TABLE_ADDR,
49 .runtime = EFI_INVALID_TABLE_ADDR,
50 .config_table = EFI_INVALID_TABLE_ADDR,
51 .esrt = EFI_INVALID_TABLE_ADDR,
52 .properties_table = EFI_INVALID_TABLE_ADDR,
53 .mem_attr_table = EFI_INVALID_TABLE_ADDR,
54 .rng_seed = EFI_INVALID_TABLE_ADDR,
55 .tpm_log = EFI_INVALID_TABLE_ADDR
56};
57EXPORT_SYMBOL(efi);
58
59static unsigned long *efi_tables[] = {
60 &efi.mps,
61 &efi.acpi,
62 &efi.acpi20,
63 &efi.smbios,
64 &efi.smbios3,
65 &efi.sal_systab,
66 &efi.boot_info,
67 &efi.hcdp,
68 &efi.uga,
69 &efi.uv_systab,
70 &efi.fw_vendor,
71 &efi.runtime,
72 &efi.config_table,
73 &efi.esrt,
74 &efi.properties_table,
75 &efi.mem_attr_table,
76};
77
78struct mm_struct efi_mm = {
79 .mm_rb = RB_ROOT,
80 .mm_users = ATOMIC_INIT(2),
81 .mm_count = ATOMIC_INIT(1),
82 .mmap_sem = __RWSEM_INITIALIZER(efi_mm.mmap_sem),
83 .page_table_lock = __SPIN_LOCK_UNLOCKED(efi_mm.page_table_lock),
84 .mmlist = LIST_HEAD_INIT(efi_mm.mmlist),
85};
86
87static bool disable_runtime;
88static int __init setup_noefi(char *arg)
89{
90 disable_runtime = true;
91 return 0;
92}
93early_param("noefi", setup_noefi);
94
95bool efi_runtime_disabled(void)
96{
97 return disable_runtime;
98}
99
100static int __init parse_efi_cmdline(char *str)
101{
102 if (!str) {
103 pr_warn("need at least one option\n");
104 return -EINVAL;
105 }
106
107 if (parse_option_str(str, "debug"))
108 set_bit(EFI_DBG, &efi.flags);
109
110 if (parse_option_str(str, "noruntime"))
111 disable_runtime = true;
112
113 return 0;
114}
115early_param("efi", parse_efi_cmdline);
116
117struct kobject *efi_kobj;
118
119
120
121
122
123
124
125static ssize_t systab_show(struct kobject *kobj,
126 struct kobj_attribute *attr, char *buf)
127{
128 char *str = buf;
129
130 if (!kobj || !buf)
131 return -EINVAL;
132
133 if (efi.mps != EFI_INVALID_TABLE_ADDR)
134 str += sprintf(str, "MPS=0x%lx\n", efi.mps);
135 if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
136 str += sprintf(str, "ACPI20=0x%lx\n", efi.acpi20);
137 if (efi.acpi != EFI_INVALID_TABLE_ADDR)
138 str += sprintf(str, "ACPI=0x%lx\n", efi.acpi);
139
140
141
142
143
144 if (efi.smbios3 != EFI_INVALID_TABLE_ADDR)
145 str += sprintf(str, "SMBIOS3=0x%lx\n", efi.smbios3);
146 if (efi.smbios != EFI_INVALID_TABLE_ADDR)
147 str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios);
148 if (efi.hcdp != EFI_INVALID_TABLE_ADDR)
149 str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp);
150 if (efi.boot_info != EFI_INVALID_TABLE_ADDR)
151 str += sprintf(str, "BOOTINFO=0x%lx\n", efi.boot_info);
152 if (efi.uga != EFI_INVALID_TABLE_ADDR)
153 str += sprintf(str, "UGA=0x%lx\n", efi.uga);
154
155 return str - buf;
156}
157
158static struct kobj_attribute efi_attr_systab = __ATTR_RO_MODE(systab, 0400);
159
160#define EFI_FIELD(var) efi.var
161
162#define EFI_ATTR_SHOW(name) \
163static ssize_t name##_show(struct kobject *kobj, \
164 struct kobj_attribute *attr, char *buf) \
165{ \
166 return sprintf(buf, "0x%lx\n", EFI_FIELD(name)); \
167}
168
169EFI_ATTR_SHOW(fw_vendor);
170EFI_ATTR_SHOW(runtime);
171EFI_ATTR_SHOW(config_table);
172
173static ssize_t fw_platform_size_show(struct kobject *kobj,
174 struct kobj_attribute *attr, char *buf)
175{
176 return sprintf(buf, "%d\n", efi_enabled(EFI_64BIT) ? 64 : 32);
177}
178
179static struct kobj_attribute efi_attr_fw_vendor = __ATTR_RO(fw_vendor);
180static struct kobj_attribute efi_attr_runtime = __ATTR_RO(runtime);
181static struct kobj_attribute efi_attr_config_table = __ATTR_RO(config_table);
182static struct kobj_attribute efi_attr_fw_platform_size =
183 __ATTR_RO(fw_platform_size);
184
185static struct attribute *efi_subsys_attrs[] = {
186 &efi_attr_systab.attr,
187 &efi_attr_fw_vendor.attr,
188 &efi_attr_runtime.attr,
189 &efi_attr_config_table.attr,
190 &efi_attr_fw_platform_size.attr,
191 NULL,
192};
193
194static umode_t efi_attr_is_visible(struct kobject *kobj,
195 struct attribute *attr, int n)
196{
197 if (attr == &efi_attr_fw_vendor.attr) {
198 if (efi_enabled(EFI_PARAVIRT) ||
199 efi.fw_vendor == EFI_INVALID_TABLE_ADDR)
200 return 0;
201 } else if (attr == &efi_attr_runtime.attr) {
202 if (efi.runtime == EFI_INVALID_TABLE_ADDR)
203 return 0;
204 } else if (attr == &efi_attr_config_table.attr) {
205 if (efi.config_table == EFI_INVALID_TABLE_ADDR)
206 return 0;
207 }
208
209 return attr->mode;
210}
211
212static const struct attribute_group efi_subsys_attr_group = {
213 .attrs = efi_subsys_attrs,
214 .is_visible = efi_attr_is_visible,
215};
216
217static struct efivars generic_efivars;
218static struct efivar_operations generic_ops;
219
220static int generic_ops_register(void)
221{
222 generic_ops.get_variable = efi.get_variable;
223 generic_ops.set_variable = efi.set_variable;
224 generic_ops.set_variable_nonblocking = efi.set_variable_nonblocking;
225 generic_ops.get_next_variable = efi.get_next_variable;
226 generic_ops.query_variable_store = efi_query_variable_store;
227
228 return efivars_register(&generic_efivars, &generic_ops, efi_kobj);
229}
230
231static void generic_ops_unregister(void)
232{
233 efivars_unregister(&generic_efivars);
234}
235
236#if IS_ENABLED(CONFIG_ACPI)
237#define EFIVAR_SSDT_NAME_MAX 16
238static char efivar_ssdt[EFIVAR_SSDT_NAME_MAX] __initdata;
239static int __init efivar_ssdt_setup(char *str)
240{
241 if (strlen(str) < sizeof(efivar_ssdt))
242 memcpy(efivar_ssdt, str, strlen(str));
243 else
244 pr_warn("efivar_ssdt: name too long: %s\n", str);
245 return 0;
246}
247__setup("efivar_ssdt=", efivar_ssdt_setup);
248
249static __init int efivar_ssdt_iter(efi_char16_t *name, efi_guid_t vendor,
250 unsigned long name_size, void *data)
251{
252 struct efivar_entry *entry;
253 struct list_head *list = data;
254 char utf8_name[EFIVAR_SSDT_NAME_MAX];
255 int limit = min_t(unsigned long, EFIVAR_SSDT_NAME_MAX, name_size);
256
257 ucs2_as_utf8(utf8_name, name, limit - 1);
258 if (strncmp(utf8_name, efivar_ssdt, limit) != 0)
259 return 0;
260
261 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
262 if (!entry)
263 return 0;
264
265 memcpy(entry->var.VariableName, name, name_size);
266 memcpy(&entry->var.VendorGuid, &vendor, sizeof(efi_guid_t));
267
268 efivar_entry_add(entry, list);
269
270 return 0;
271}
272
273static __init int efivar_ssdt_load(void)
274{
275 LIST_HEAD(entries);
276 struct efivar_entry *entry, *aux;
277 unsigned long size;
278 void *data;
279 int ret;
280
281 ret = efivar_init(efivar_ssdt_iter, &entries, true, &entries);
282
283 list_for_each_entry_safe(entry, aux, &entries, list) {
284 pr_info("loading SSDT from variable %s-%pUl\n", efivar_ssdt,
285 &entry->var.VendorGuid);
286
287 list_del(&entry->list);
288
289 ret = efivar_entry_size(entry, &size);
290 if (ret) {
291 pr_err("failed to get var size\n");
292 goto free_entry;
293 }
294
295 data = kmalloc(size, GFP_KERNEL);
296 if (!data) {
297 ret = -ENOMEM;
298 goto free_entry;
299 }
300
301 ret = efivar_entry_get(entry, NULL, &size, data);
302 if (ret) {
303 pr_err("failed to get var data\n");
304 goto free_data;
305 }
306
307 ret = acpi_load_table(data);
308 if (ret) {
309 pr_err("failed to load table: %d\n", ret);
310 goto free_data;
311 }
312
313 goto free_entry;
314
315free_data:
316 kfree(data);
317
318free_entry:
319 kfree(entry);
320 }
321
322 return ret;
323}
324#else
325static inline int efivar_ssdt_load(void) { return 0; }
326#endif
327
328
329
330
331
332
333static int __init efisubsys_init(void)
334{
335 int error;
336
337 if (!efi_enabled(EFI_BOOT))
338 return 0;
339
340
341 efi_kobj = kobject_create_and_add("efi", firmware_kobj);
342 if (!efi_kobj) {
343 pr_err("efi: Firmware registration failed.\n");
344 return -ENOMEM;
345 }
346
347 error = generic_ops_register();
348 if (error)
349 goto err_put;
350
351 if (efi_enabled(EFI_RUNTIME_SERVICES))
352 efivar_ssdt_load();
353
354 error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group);
355 if (error) {
356 pr_err("efi: Sysfs attribute export failed with error %d.\n",
357 error);
358 goto err_unregister;
359 }
360
361 error = efi_runtime_map_init(efi_kobj);
362 if (error)
363 goto err_remove_group;
364
365
366 error = sysfs_create_mount_point(efi_kobj, "efivars");
367 if (error) {
368 pr_err("efivars: Subsystem registration failed.\n");
369 goto err_remove_group;
370 }
371
372 return 0;
373
374err_remove_group:
375 sysfs_remove_group(efi_kobj, &efi_subsys_attr_group);
376err_unregister:
377 generic_ops_unregister();
378err_put:
379 kobject_put(efi_kobj);
380 return error;
381}
382
383subsys_initcall(efisubsys_init);
384
385
386
387
388
389
390
391int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
392{
393 efi_memory_desc_t *md;
394
395 if (!efi_enabled(EFI_MEMMAP)) {
396 pr_err_once("EFI_MEMMAP is not enabled.\n");
397 return -EINVAL;
398 }
399
400 if (!out_md) {
401 pr_err_once("out_md is null.\n");
402 return -EINVAL;
403 }
404
405 for_each_efi_memory_desc(md) {
406 u64 size;
407 u64 end;
408
409 if (!(md->attribute & EFI_MEMORY_RUNTIME) &&
410 md->type != EFI_BOOT_SERVICES_DATA &&
411 md->type != EFI_RUNTIME_SERVICES_DATA) {
412 continue;
413 }
414
415 size = md->num_pages << EFI_PAGE_SHIFT;
416 end = md->phys_addr + size;
417 if (phys_addr >= md->phys_addr && phys_addr < end) {
418 memcpy(out_md, md, sizeof(*out_md));
419 return 0;
420 }
421 }
422 return -ENOENT;
423}
424
425
426
427
428u64 __init efi_mem_desc_end(efi_memory_desc_t *md)
429{
430 u64 size = md->num_pages << EFI_PAGE_SHIFT;
431 u64 end = md->phys_addr + size;
432 return end;
433}
434
435void __init __weak efi_arch_mem_reserve(phys_addr_t addr, u64 size) {}
436
437
438
439
440
441
442
443
444
445
446
447
448
449void __init efi_mem_reserve(phys_addr_t addr, u64 size)
450{
451 if (!memblock_is_region_reserved(addr, size))
452 memblock_reserve(addr, size);
453
454
455
456
457
458
459
460
461 efi_arch_mem_reserve(addr, size);
462}
463
464static __initdata efi_config_table_type_t common_tables[] = {
465 {ACPI_20_TABLE_GUID, "ACPI 2.0", &efi.acpi20},
466 {ACPI_TABLE_GUID, "ACPI", &efi.acpi},
467 {HCDP_TABLE_GUID, "HCDP", &efi.hcdp},
468 {MPS_TABLE_GUID, "MPS", &efi.mps},
469 {SAL_SYSTEM_TABLE_GUID, "SALsystab", &efi.sal_systab},
470 {SMBIOS_TABLE_GUID, "SMBIOS", &efi.smbios},
471 {SMBIOS3_TABLE_GUID, "SMBIOS 3.0", &efi.smbios3},
472 {UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga},
473 {EFI_SYSTEM_RESOURCE_TABLE_GUID, "ESRT", &efi.esrt},
474 {EFI_PROPERTIES_TABLE_GUID, "PROP", &efi.properties_table},
475 {EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", &efi.mem_attr_table},
476 {LINUX_EFI_RANDOM_SEED_TABLE_GUID, "RNG", &efi.rng_seed},
477 {LINUX_EFI_TPM_EVENT_LOG_GUID, "TPMEventLog", &efi.tpm_log},
478 {NULL_GUID, NULL, NULL},
479};
480
481static __init int match_config_table(efi_guid_t *guid,
482 unsigned long table,
483 efi_config_table_type_t *table_types)
484{
485 int i;
486
487 if (table_types) {
488 for (i = 0; efi_guidcmp(table_types[i].guid, NULL_GUID); i++) {
489 if (!efi_guidcmp(*guid, table_types[i].guid)) {
490 *(table_types[i].ptr) = table;
491 if (table_types[i].name)
492 pr_cont(" %s=0x%lx ",
493 table_types[i].name, table);
494 return 1;
495 }
496 }
497 }
498
499 return 0;
500}
501
502int __init efi_config_parse_tables(void *config_tables, int count, int sz,
503 efi_config_table_type_t *arch_tables)
504{
505 void *tablep;
506 int i;
507
508 tablep = config_tables;
509 pr_info("");
510 for (i = 0; i < count; i++) {
511 efi_guid_t guid;
512 unsigned long table;
513
514 if (efi_enabled(EFI_64BIT)) {
515 u64 table64;
516 guid = ((efi_config_table_64_t *)tablep)->guid;
517 table64 = ((efi_config_table_64_t *)tablep)->table;
518 table = table64;
519#ifndef CONFIG_64BIT
520 if (table64 >> 32) {
521 pr_cont("\n");
522 pr_err("Table located above 4GB, disabling EFI.\n");
523 return -EINVAL;
524 }
525#endif
526 } else {
527 guid = ((efi_config_table_32_t *)tablep)->guid;
528 table = ((efi_config_table_32_t *)tablep)->table;
529 }
530
531 if (!match_config_table(&guid, table, common_tables))
532 match_config_table(&guid, table, arch_tables);
533
534 tablep += sz;
535 }
536 pr_cont("\n");
537 set_bit(EFI_CONFIG_TABLES, &efi.flags);
538
539 if (efi.rng_seed != EFI_INVALID_TABLE_ADDR) {
540 struct linux_efi_random_seed *seed;
541 u32 size = 0;
542
543 seed = early_memremap(efi.rng_seed, sizeof(*seed));
544 if (seed != NULL) {
545 size = seed->size;
546 early_memunmap(seed, sizeof(*seed));
547 } else {
548 pr_err("Could not map UEFI random seed!\n");
549 }
550 if (size > 0) {
551 seed = early_memremap(efi.rng_seed,
552 sizeof(*seed) + size);
553 if (seed != NULL) {
554 pr_notice("seeding entropy pool\n");
555 add_device_randomness(seed->bits, seed->size);
556 early_memunmap(seed, sizeof(*seed) + size);
557 } else {
558 pr_err("Could not map UEFI random seed!\n");
559 }
560 }
561 }
562
563 if (efi_enabled(EFI_MEMMAP))
564 efi_memattr_init();
565
566 efi_tpm_eventlog_init();
567
568
569 if (efi.properties_table != EFI_INVALID_TABLE_ADDR) {
570 efi_properties_table_t *tbl;
571
572 tbl = early_memremap(efi.properties_table, sizeof(*tbl));
573 if (tbl == NULL) {
574 pr_err("Could not map Properties table!\n");
575 return -ENOMEM;
576 }
577
578 if (tbl->memory_protection_attribute &
579 EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA)
580 set_bit(EFI_NX_PE_DATA, &efi.flags);
581
582 early_memunmap(tbl, sizeof(*tbl));
583 }
584
585 return 0;
586}
587
588int __init efi_config_init(efi_config_table_type_t *arch_tables)
589{
590 void *config_tables;
591 int sz, ret;
592
593 if (efi_enabled(EFI_64BIT))
594 sz = sizeof(efi_config_table_64_t);
595 else
596 sz = sizeof(efi_config_table_32_t);
597
598
599
600
601 config_tables = early_memremap(efi.systab->tables,
602 efi.systab->nr_tables * sz);
603 if (config_tables == NULL) {
604 pr_err("Could not map Configuration table!\n");
605 return -ENOMEM;
606 }
607
608 ret = efi_config_parse_tables(config_tables, efi.systab->nr_tables, sz,
609 arch_tables);
610
611 early_memunmap(config_tables, efi.systab->nr_tables * sz);
612 return ret;
613}
614
615#ifdef CONFIG_EFI_VARS_MODULE
616static int __init efi_load_efivars(void)
617{
618 struct platform_device *pdev;
619
620 if (!efi_enabled(EFI_RUNTIME_SERVICES))
621 return 0;
622
623 pdev = platform_device_register_simple("efivars", 0, NULL, 0);
624 return PTR_ERR_OR_ZERO(pdev);
625}
626device_initcall(efi_load_efivars);
627#endif
628
629#ifdef CONFIG_EFI_PARAMS_FROM_FDT
630
631#define UEFI_PARAM(name, prop, field) \
632 { \
633 { name }, \
634 { prop }, \
635 offsetof(struct efi_fdt_params, field), \
636 FIELD_SIZEOF(struct efi_fdt_params, field) \
637 }
638
639struct params {
640 const char name[32];
641 const char propname[32];
642 int offset;
643 int size;
644};
645
646static __initdata struct params fdt_params[] = {
647 UEFI_PARAM("System Table", "linux,uefi-system-table", system_table),
648 UEFI_PARAM("MemMap Address", "linux,uefi-mmap-start", mmap),
649 UEFI_PARAM("MemMap Size", "linux,uefi-mmap-size", mmap_size),
650 UEFI_PARAM("MemMap Desc. Size", "linux,uefi-mmap-desc-size", desc_size),
651 UEFI_PARAM("MemMap Desc. Version", "linux,uefi-mmap-desc-ver", desc_ver)
652};
653
654static __initdata struct params xen_fdt_params[] = {
655 UEFI_PARAM("System Table", "xen,uefi-system-table", system_table),
656 UEFI_PARAM("MemMap Address", "xen,uefi-mmap-start", mmap),
657 UEFI_PARAM("MemMap Size", "xen,uefi-mmap-size", mmap_size),
658 UEFI_PARAM("MemMap Desc. Size", "xen,uefi-mmap-desc-size", desc_size),
659 UEFI_PARAM("MemMap Desc. Version", "xen,uefi-mmap-desc-ver", desc_ver)
660};
661
662#define EFI_FDT_PARAMS_SIZE ARRAY_SIZE(fdt_params)
663
664static __initdata struct {
665 const char *uname;
666 const char *subnode;
667 struct params *params;
668} dt_params[] = {
669 { "hypervisor", "uefi", xen_fdt_params },
670 { "chosen", NULL, fdt_params },
671};
672
673struct param_info {
674 int found;
675 void *params;
676 const char *missing;
677};
678
679static int __init __find_uefi_params(unsigned long node,
680 struct param_info *info,
681 struct params *params)
682{
683 const void *prop;
684 void *dest;
685 u64 val;
686 int i, len;
687
688 for (i = 0; i < EFI_FDT_PARAMS_SIZE; i++) {
689 prop = of_get_flat_dt_prop(node, params[i].propname, &len);
690 if (!prop) {
691 info->missing = params[i].name;
692 return 0;
693 }
694
695 dest = info->params + params[i].offset;
696 info->found++;
697
698 val = of_read_number(prop, len / sizeof(u32));
699
700 if (params[i].size == sizeof(u32))
701 *(u32 *)dest = val;
702 else
703 *(u64 *)dest = val;
704
705 if (efi_enabled(EFI_DBG))
706 pr_info(" %s: 0x%0*llx\n", params[i].name,
707 params[i].size * 2, val);
708 }
709
710 return 1;
711}
712
713static int __init fdt_find_uefi_params(unsigned long node, const char *uname,
714 int depth, void *data)
715{
716 struct param_info *info = data;
717 int i;
718
719 for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
720 const char *subnode = dt_params[i].subnode;
721
722 if (depth != 1 || strcmp(uname, dt_params[i].uname) != 0) {
723 info->missing = dt_params[i].params[0].name;
724 continue;
725 }
726
727 if (subnode) {
728 int err = of_get_flat_dt_subnode_by_name(node, subnode);
729
730 if (err < 0)
731 return 0;
732
733 node = err;
734 }
735
736 return __find_uefi_params(node, info, dt_params[i].params);
737 }
738
739 return 0;
740}
741
742int __init efi_get_fdt_params(struct efi_fdt_params *params)
743{
744 struct param_info info;
745 int ret;
746
747 pr_info("Getting EFI parameters from FDT:\n");
748
749 info.found = 0;
750 info.params = params;
751
752 ret = of_scan_flat_dt(fdt_find_uefi_params, &info);
753 if (!info.found)
754 pr_info("UEFI not found.\n");
755 else if (!ret)
756 pr_err("Can't find '%s' in device tree!\n",
757 info.missing);
758
759 return ret;
760}
761#endif
762
763static __initdata char memory_type_name[][20] = {
764 "Reserved",
765 "Loader Code",
766 "Loader Data",
767 "Boot Code",
768 "Boot Data",
769 "Runtime Code",
770 "Runtime Data",
771 "Conventional Memory",
772 "Unusable Memory",
773 "ACPI Reclaim Memory",
774 "ACPI Memory NVS",
775 "Memory Mapped I/O",
776 "MMIO Port Space",
777 "PAL Code",
778 "Persistent Memory",
779};
780
781char * __init efi_md_typeattr_format(char *buf, size_t size,
782 const efi_memory_desc_t *md)
783{
784 char *pos;
785 int type_len;
786 u64 attr;
787
788 pos = buf;
789 if (md->type >= ARRAY_SIZE(memory_type_name))
790 type_len = snprintf(pos, size, "[type=%u", md->type);
791 else
792 type_len = snprintf(pos, size, "[%-*s",
793 (int)(sizeof(memory_type_name[0]) - 1),
794 memory_type_name[md->type]);
795 if (type_len >= size)
796 return buf;
797
798 pos += type_len;
799 size -= type_len;
800
801 attr = md->attribute;
802 if (attr & ~(EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT |
803 EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_RO |
804 EFI_MEMORY_WP | EFI_MEMORY_RP | EFI_MEMORY_XP |
805 EFI_MEMORY_NV |
806 EFI_MEMORY_RUNTIME | EFI_MEMORY_MORE_RELIABLE))
807 snprintf(pos, size, "|attr=0x%016llx]",
808 (unsigned long long)attr);
809 else
810 snprintf(pos, size,
811 "|%3s|%2s|%2s|%2s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]",
812 attr & EFI_MEMORY_RUNTIME ? "RUN" : "",
813 attr & EFI_MEMORY_MORE_RELIABLE ? "MR" : "",
814 attr & EFI_MEMORY_NV ? "NV" : "",
815 attr & EFI_MEMORY_XP ? "XP" : "",
816 attr & EFI_MEMORY_RP ? "RP" : "",
817 attr & EFI_MEMORY_WP ? "WP" : "",
818 attr & EFI_MEMORY_RO ? "RO" : "",
819 attr & EFI_MEMORY_UCE ? "UCE" : "",
820 attr & EFI_MEMORY_WB ? "WB" : "",
821 attr & EFI_MEMORY_WT ? "WT" : "",
822 attr & EFI_MEMORY_WC ? "WC" : "",
823 attr & EFI_MEMORY_UC ? "UC" : "");
824 return buf;
825}
826
827
828
829
830
831#ifndef CONFIG_IA64
832
833
834
835
836
837
838
839
840u64 efi_mem_attributes(unsigned long phys_addr)
841{
842 efi_memory_desc_t *md;
843
844 if (!efi_enabled(EFI_MEMMAP))
845 return 0;
846
847 for_each_efi_memory_desc(md) {
848 if ((md->phys_addr <= phys_addr) &&
849 (phys_addr < (md->phys_addr +
850 (md->num_pages << EFI_PAGE_SHIFT))))
851 return md->attribute;
852 }
853 return 0;
854}
855
856
857
858
859
860
861
862
863
864int efi_mem_type(unsigned long phys_addr)
865{
866 const efi_memory_desc_t *md;
867
868 if (!efi_enabled(EFI_MEMMAP))
869 return -ENOTSUPP;
870
871 for_each_efi_memory_desc(md) {
872 if ((md->phys_addr <= phys_addr) &&
873 (phys_addr < (md->phys_addr +
874 (md->num_pages << EFI_PAGE_SHIFT))))
875 return md->type;
876 }
877 return -EINVAL;
878}
879#endif
880
881int efi_status_to_err(efi_status_t status)
882{
883 int err;
884
885 switch (status) {
886 case EFI_SUCCESS:
887 err = 0;
888 break;
889 case EFI_INVALID_PARAMETER:
890 err = -EINVAL;
891 break;
892 case EFI_OUT_OF_RESOURCES:
893 err = -ENOSPC;
894 break;
895 case EFI_DEVICE_ERROR:
896 err = -EIO;
897 break;
898 case EFI_WRITE_PROTECTED:
899 err = -EROFS;
900 break;
901 case EFI_SECURITY_VIOLATION:
902 err = -EACCES;
903 break;
904 case EFI_NOT_FOUND:
905 err = -ENOENT;
906 break;
907 case EFI_ABORTED:
908 err = -EINTR;
909 break;
910 default:
911 err = -EINVAL;
912 }
913
914 return err;
915}
916
917bool efi_is_table_address(unsigned long phys_addr)
918{
919 unsigned int i;
920
921 if (phys_addr == EFI_INVALID_TABLE_ADDR)
922 return false;
923
924 for (i = 0; i < ARRAY_SIZE(efi_tables); i++)
925 if (*(efi_tables[i]) == phys_addr)
926 return true;
927
928 return false;
929}
930
931#ifdef CONFIG_KEXEC
932static int update_efi_random_seed(struct notifier_block *nb,
933 unsigned long code, void *unused)
934{
935 struct linux_efi_random_seed *seed;
936 u32 size = 0;
937
938 if (!kexec_in_progress)
939 return NOTIFY_DONE;
940
941 seed = memremap(efi.rng_seed, sizeof(*seed), MEMREMAP_WB);
942 if (seed != NULL) {
943 size = min(seed->size, EFI_RANDOM_SEED_SIZE);
944 memunmap(seed);
945 } else {
946 pr_err("Could not map UEFI random seed!\n");
947 }
948 if (size > 0) {
949 seed = memremap(efi.rng_seed, sizeof(*seed) + size,
950 MEMREMAP_WB);
951 if (seed != NULL) {
952 seed->size = size;
953 get_random_bytes(seed->bits, seed->size);
954 memunmap(seed);
955 } else {
956 pr_err("Could not map UEFI random seed!\n");
957 }
958 }
959 return NOTIFY_DONE;
960}
961
962static struct notifier_block efi_random_seed_nb = {
963 .notifier_call = update_efi_random_seed,
964};
965
966static int register_update_efi_random_seed(void)
967{
968 if (efi.rng_seed == EFI_INVALID_TABLE_ADDR)
969 return 0;
970 return register_reboot_notifier(&efi_random_seed_nb);
971}
972late_initcall(register_update_efi_random_seed);
973#endif
974