fixvideo.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  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. static struct grub_video_patch
  26. {
  27. const char *name;
  28. grub_uint32_t pci_id;
  29. grub_uint32_t mmio_bar;
  30. grub_uint32_t mmio_reg;
  31. grub_uint32_t mmio_old;
  32. } video_patches[] =
  33. {
  34. {"Intel 945GM", 0x27a28086, 0, 0x71184, 0x1000000}, /* DSPBBASE */
  35. {"Intel 965GM", 0x2a028086, 0, 0x7119C, 0x1000000}, /* DSPBSURF */
  36. {0, 0, 0, 0, 0}
  37. };
  38. static int
  39. scan_card (grub_pci_device_t dev, grub_pci_id_t pciid,
  40. void *closure __attribute__((unused)))
  41. {
  42. grub_pci_address_t addr;
  43. addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
  44. if (grub_pci_read_byte (addr + 3) == 0x3)
  45. {
  46. struct grub_video_patch *p = video_patches;
  47. while (p->name)
  48. {
  49. if (p->pci_id == pciid)
  50. {
  51. grub_target_addr_t base;
  52. grub_printf ("Found graphic card: %s\n", p->name);
  53. addr += 8 + p->mmio_bar * 4;
  54. base = grub_pci_read (addr);
  55. if ((! base) || (base & GRUB_PCI_ADDR_SPACE_IO) ||
  56. (base & GRUB_PCI_ADDR_MEM_PREFETCH))
  57. grub_printf ("Invalid MMIO bar %d\n", p->mmio_bar);
  58. else
  59. {
  60. base &= GRUB_PCI_ADDR_MEM_MASK;
  61. base += p->mmio_reg;
  62. if (*((volatile grub_uint32_t *) base) != p->mmio_old)
  63. grub_printf ("Old value don't match\n");
  64. else
  65. {
  66. *((volatile grub_uint32_t *) base) = 0;
  67. if (*((volatile grub_uint32_t *) base))
  68. grub_printf ("Set MMIO fails\n");
  69. }
  70. }
  71. return 1;
  72. }
  73. p++;
  74. }
  75. grub_printf ("Unknown graphic card: %x\n", pciid);
  76. }
  77. return 0;
  78. }
  79. static grub_err_t
  80. grub_cmd_fixvideo (grub_command_t cmd __attribute__ ((unused)),
  81. int argc __attribute__ ((unused)),
  82. char *argv[] __attribute__ ((unused)))
  83. {
  84. grub_pci_iterate (scan_card, 0);
  85. return 0;
  86. }
  87. static grub_command_t cmd_fixvideo;
  88. GRUB_MOD_INIT(fixvideo)
  89. {
  90. cmd_fixvideo = grub_register_command ("fix_video", grub_cmd_fixvideo,
  91. 0, N_("Fix video problem."));
  92. }
  93. GRUB_MOD_FINI(fixvideo)
  94. {
  95. grub_unregister_command (cmd_fixvideo);
  96. }