efi.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /*
  2. * efi.c - EFI subsystem
  3. *
  4. * Copyright (C) 2001,2003,2004 Dell <Matt_Domsch@dell.com>
  5. * Copyright (C) 2004 Intel Corporation <matthew.e.tolentino@intel.com>
  6. * Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
  7. *
  8. * This code registers /sys/firmware/efi{,/efivars} when EFI is supported,
  9. * allowing the efivarfs to be mounted or the efivars module to be loaded.
  10. * The existance of /sys/firmware/efi may also be used by userspace to
  11. * determine that the system supports EFI.
  12. *
  13. * This file is released under the GPLv2.
  14. */
  15. #include <linux/kobject.h>
  16. #include <linux/module.h>
  17. #include <linux/init.h>
  18. #include <linux/device.h>
  19. #include <linux/efi.h>
  20. static struct kobject *efi_kobj;
  21. static struct kobject *efivars_kobj;
  22. /*
  23. * Let's not leave out systab information that snuck into
  24. * the efivars driver
  25. */
  26. static ssize_t systab_show(struct kobject *kobj,
  27. struct kobj_attribute *attr, char *buf)
  28. {
  29. char *str = buf;
  30. if (!kobj || !buf)
  31. return -EINVAL;
  32. if (efi.mps != EFI_INVALID_TABLE_ADDR)
  33. str += sprintf(str, "MPS=0x%lx\n", efi.mps);
  34. if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
  35. str += sprintf(str, "ACPI20=0x%lx\n", efi.acpi20);
  36. if (efi.acpi != EFI_INVALID_TABLE_ADDR)
  37. str += sprintf(str, "ACPI=0x%lx\n", efi.acpi);
  38. if (efi.smbios != EFI_INVALID_TABLE_ADDR)
  39. str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios);
  40. if (efi.hcdp != EFI_INVALID_TABLE_ADDR)
  41. str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp);
  42. if (efi.boot_info != EFI_INVALID_TABLE_ADDR)
  43. str += sprintf(str, "BOOTINFO=0x%lx\n", efi.boot_info);
  44. if (efi.uga != EFI_INVALID_TABLE_ADDR)
  45. str += sprintf(str, "UGA=0x%lx\n", efi.uga);
  46. return str - buf;
  47. }
  48. static struct kobj_attribute efi_attr_systab =
  49. __ATTR(systab, 0400, systab_show, NULL);
  50. static struct attribute *efi_subsys_attrs[] = {
  51. &efi_attr_systab.attr,
  52. NULL, /* maybe more in the future? */
  53. };
  54. static struct attribute_group efi_subsys_attr_group = {
  55. .attrs = efi_subsys_attrs,
  56. };
  57. static struct efivars generic_efivars;
  58. static struct efivar_operations generic_ops;
  59. static int generic_ops_register(void)
  60. {
  61. generic_ops.get_variable = efi.get_variable;
  62. generic_ops.set_variable = efi.set_variable;
  63. generic_ops.get_next_variable = efi.get_next_variable;
  64. generic_ops.query_variable_store = efi_query_variable_store;
  65. return efivars_register(&generic_efivars, &generic_ops, efi_kobj);
  66. }
  67. static void generic_ops_unregister(void)
  68. {
  69. efivars_unregister(&generic_efivars);
  70. }
  71. /*
  72. * We register the efi subsystem with the firmware subsystem and the
  73. * efivars subsystem with the efi subsystem, if the system was booted with
  74. * EFI.
  75. */
  76. static int __init efisubsys_init(void)
  77. {
  78. int error;
  79. if (!efi_enabled(EFI_BOOT))
  80. return 0;
  81. /* We register the efi directory at /sys/firmware/efi */
  82. efi_kobj = kobject_create_and_add("efi", firmware_kobj);
  83. if (!efi_kobj) {
  84. pr_err("efi: Firmware registration failed.\n");
  85. return -ENOMEM;
  86. }
  87. error = generic_ops_register();
  88. if (error)
  89. goto err_put;
  90. error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group);
  91. if (error) {
  92. pr_err("efi: Sysfs attribute export failed with error %d.\n",
  93. error);
  94. goto err_unregister;
  95. }
  96. /* and the standard mountpoint for efivarfs */
  97. efivars_kobj = kobject_create_and_add("efivars", efi_kobj);
  98. if (!efivars_kobj) {
  99. pr_err("efivars: Subsystem registration failed.\n");
  100. error = -ENOMEM;
  101. goto err_remove_group;
  102. }
  103. return 0;
  104. err_remove_group:
  105. sysfs_remove_group(efi_kobj, &efi_subsys_attr_group);
  106. err_unregister:
  107. generic_ops_unregister();
  108. err_put:
  109. kobject_put(efi_kobj);
  110. return error;
  111. }
  112. subsys_initcall(efisubsys_init);