fixvideo.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /* fixvideo.c - fix video problem in efi */
  2. /*
  3. * GRUB -- GRand Unified Bootloader
  4. * Copyright (C) 2009 Free Software Foundation, Inc.
  5. *
  6. * GRUB is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * GRUB is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <grub/dl.h>
  20. #include <grub/misc.h>
  21. #include <grub/file.h>
  22. #include <grub/pci.h>
  23. #include <grub/command.h>
  24. #include <grub/i18n.h>
  25. #include <grub/mm.h>
  26. GRUB_MOD_LICENSE ("GPLv3+");
  27. static struct grub_video_patch
  28. {
  29. const char *name;
  30. grub_uint32_t pci_id;
  31. grub_uint32_t mmio_bar;
  32. grub_uint32_t mmio_reg;
  33. grub_uint32_t mmio_old;
  34. } video_patches[] =
  35. {
  36. {"Intel 945GM", 0x27a28086, 0, 0x71184, 0x1000000}, /* DSPBBASE */
  37. {"Intel 965GM", 0x2a028086, 0, 0x7119C, 0x1000000}, /* DSPBSURF */
  38. {0, 0, 0, 0, 0}
  39. };
  40. static int
  41. scan_card (grub_pci_device_t dev, grub_pci_id_t pciid,
  42. void *data __attribute__ ((unused)))
  43. {
  44. grub_pci_address_t addr;
  45. addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
  46. if (grub_pci_read_byte (addr + 3) == 0x3)
  47. {
  48. struct grub_video_patch *p = video_patches;
  49. while (p->name)
  50. {
  51. if (p->pci_id == pciid)
  52. {
  53. grub_addr_t base;
  54. grub_dprintf ("fixvideo", "Found graphic card: %s\n", p->name);
  55. addr += 8 + p->mmio_bar * 4;
  56. base = grub_pci_read (addr);
  57. if ((! base) || (base & GRUB_PCI_ADDR_SPACE_IO) ||
  58. (base & GRUB_PCI_ADDR_MEM_PREFETCH))
  59. grub_dprintf ("fixvideo", "Invalid MMIO bar %d\n", p->mmio_bar);
  60. else
  61. {
  62. base &= GRUB_PCI_ADDR_MEM_MASK;
  63. base += p->mmio_reg;
  64. if (*((volatile grub_uint32_t *) base) != p->mmio_old)
  65. grub_dprintf ("fixvideo", "Old value doesn't match\n");
  66. else
  67. {
  68. *((volatile grub_uint32_t *) base) = 0;
  69. if (*((volatile grub_uint32_t *) base))
  70. grub_dprintf ("fixvideo", "Setting MMIO fails\n");
  71. }
  72. }
  73. return 1;
  74. }
  75. p++;
  76. }
  77. grub_dprintf ("fixvideo", "Unknown graphic card: %x\n", pciid);
  78. }
  79. return 0;
  80. }
  81. static grub_err_t
  82. grub_cmd_fixvideo (grub_command_t cmd __attribute__ ((unused)),
  83. int argc __attribute__ ((unused)),
  84. char *argv[] __attribute__ ((unused)))
  85. {
  86. grub_pci_iterate (scan_card, NULL);
  87. return 0;
  88. }
  89. static grub_command_t cmd_fixvideo;
  90. GRUB_MOD_INIT(fixvideo)
  91. {
  92. cmd_fixvideo = grub_register_command ("fix_video", grub_cmd_fixvideo,
  93. 0, N_("Fix video problem."));
  94. }
  95. GRUB_MOD_FINI(fixvideo)
  96. {
  97. grub_unregister_command (cmd_fixvideo);
  98. }