efi-bgrt.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. /*
  2. * Copyright 2012 Intel Corporation
  3. * Author: Josh Triplett <josh@joshtriplett.org>
  4. *
  5. * Based on the bgrt driver:
  6. * Copyright 2012 Red Hat, Inc <mjg@redhat.com>
  7. * Author: Matthew Garrett
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2 as
  11. * published by the Free Software Foundation.
  12. */
  13. #include <linux/kernel.h>
  14. #include <linux/init.h>
  15. #include <linux/acpi.h>
  16. #include <linux/efi.h>
  17. #include <linux/efi-bgrt.h>
  18. struct acpi_table_bgrt *bgrt_tab;
  19. void *__initdata bgrt_image;
  20. size_t __initdata bgrt_image_size;
  21. struct bmp_header {
  22. u16 id;
  23. u32 size;
  24. } __packed;
  25. void __init efi_bgrt_init(void)
  26. {
  27. acpi_status status;
  28. void __iomem *image;
  29. bool ioremapped = false;
  30. struct bmp_header bmp_header;
  31. if (acpi_disabled)
  32. return;
  33. status = acpi_get_table("BGRT", 0,
  34. (struct acpi_table_header **)&bgrt_tab);
  35. if (ACPI_FAILURE(status))
  36. return;
  37. if (bgrt_tab->header.length < sizeof(*bgrt_tab)) {
  38. pr_err("Ignoring BGRT: invalid length %u (expected %zu)\n",
  39. bgrt_tab->header.length, sizeof(*bgrt_tab));
  40. return;
  41. }
  42. if (bgrt_tab->version != 1) {
  43. pr_err("Ignoring BGRT: invalid version %u (expected 1)\n",
  44. bgrt_tab->version);
  45. return;
  46. }
  47. if (bgrt_tab->status != 1) {
  48. pr_err("Ignoring BGRT: invalid status %u (expected 1)\n",
  49. bgrt_tab->status);
  50. return;
  51. }
  52. if (bgrt_tab->image_type != 0) {
  53. pr_err("Ignoring BGRT: invalid image type %u (expected 0)\n",
  54. bgrt_tab->image_type);
  55. return;
  56. }
  57. if (!bgrt_tab->image_address) {
  58. pr_err("Ignoring BGRT: null image address\n");
  59. return;
  60. }
  61. image = efi_lookup_mapped_addr(bgrt_tab->image_address);
  62. if (!image) {
  63. image = early_ioremap(bgrt_tab->image_address,
  64. sizeof(bmp_header));
  65. ioremapped = true;
  66. if (!image) {
  67. pr_err("Ignoring BGRT: failed to map image header memory\n");
  68. return;
  69. }
  70. }
  71. memcpy_fromio(&bmp_header, image, sizeof(bmp_header));
  72. if (ioremapped)
  73. early_iounmap(image, sizeof(bmp_header));
  74. bgrt_image_size = bmp_header.size;
  75. bgrt_image = kmalloc(bgrt_image_size, GFP_KERNEL | __GFP_NOWARN);
  76. if (!bgrt_image) {
  77. pr_err("Ignoring BGRT: failed to allocate memory for image (wanted %zu bytes)\n",
  78. bgrt_image_size);
  79. return;
  80. }
  81. if (ioremapped) {
  82. image = early_ioremap(bgrt_tab->image_address,
  83. bmp_header.size);
  84. if (!image) {
  85. pr_err("Ignoring BGRT: failed to map image memory\n");
  86. kfree(bgrt_image);
  87. bgrt_image = NULL;
  88. return;
  89. }
  90. }
  91. memcpy_fromio(bgrt_image, image, bgrt_image_size);
  92. if (ioremapped)
  93. early_iounmap(image, bmp_header.size);
  94. }