Hi,

This is another update, it contains the following changes with regards
to the previous one:

1, Move loadbios command to commands/efi directory.
2, loadbios support an optional second parameter which is the int10
vector dump file.
3, The linux command enables frame buffer by default, so you don't
need video= option anymore.
4. New command fix_video to fix video register issue with efi. With
this, you can boot to console mode with agp enabled.
5, New shell script grub-dumpbios which can be used to generate the
bios dump from pc mode.

As the commands usage have changed in the previous patches, here is a
summary of what you should do with this latest patch:

1, Boot without bios dump.

This is the commands to use:

search --set /vmlinuz
fix_video
fakebios
linux /vmlinuz root=/dev/sdb1
initrd /initrd.img

2, Boot with bios dump.

First, boot to pc mode, then use script grub-dumpbios to generate the
dump files:

sudo grub-dumpbios -o /boot/

video bios dump is in vbios.bin, int10 vector is in int10.bin. /boot/
is the output directory.

Then, use the following commands in grub2:
search --set /vmlinuz
fix_video
loadbios /boot/vbios.bin /boot/int10.bin
linux /vmlinuz root=/dev/sdb1
initrd /initrd.img

Moreover, if you're booting 2.6.27-28, amd64 kernel, you need to add
noefi option.

-- 
Bean
diff --git a/commands/efi/fixvideo.c b/commands/efi/fixvideo.c
new file mode 100644
index 0000000..61f8d7b
--- /dev/null
+++ b/commands/efi/fixvideo.c
@@ -0,0 +1,106 @@
+/* fixvideo.c - fix video problem in efi */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/file.h>
+#include <grub/pci.h>
+#include <grub/command.h>
+
+static struct grub_video_patch
+{
+  const char *name;
+  grub_uint32_t pci_id;
+  grub_uint32_t mmio_bar;
+  grub_uint32_t mmio_dispa;
+  grub_uint32_t mmio_dispb;
+} video_patches[] =
+  {
+    {"Intel 965GM", 0x2a028086, 0, 0x7019C, 0x7119C}, /* DSPBSURF  */
+    {0, 0, 0, 0, 0}
+  };
+
+static int NESTED_FUNC_ATTR
+scan_card (int bus, int dev, int func, grub_pci_id_t pciid)
+{
+  grub_pci_address_t addr;
+
+  addr = grub_pci_make_address (bus, dev, func, 2);
+  if (grub_pci_read_byte (addr + 3) == 0x3)
+    {
+      struct grub_video_patch *p = video_patches;
+
+      while (p->name)
+	{
+	  if (p->pci_id == pciid)
+	    {
+	      grub_target_addr_t base;
+
+	      grub_printf ("Found graphic card: %s\n", p->name);
+	      addr += 8 + p->mmio_bar * 4;
+	      base = grub_pci_read (addr);
+	      if ((! base) || (base & GRUB_PCI_ADDR_SPACE_IO) ||
+		  (base & GRUB_PCI_ADDR_MEM_PREFETCH))
+		grub_printf ("Invalid MMIO bar %d\n", p->mmio_bar);
+	      else
+		{
+		  grub_uint32_t v;
+
+		  base &= GRUB_PCI_ADDR_MEM_MASK;
+		  v = *((volatile grub_uint32_t *) (base + p->mmio_dispa));
+		  *((volatile grub_uint32_t *) (base + p->mmio_dispb)) = v;
+		  if (*((volatile grub_uint32_t *) (base + p->mmio_dispb))
+		      != v)
+		    grub_printf ("Set MMIO fails\n");
+		}
+
+	      return 1;
+	    }
+	  p++;
+	}
+
+      grub_printf ("Unknown graphic card: %x\n", pciid);
+    }
+
+  return 0;
+}
+
+static grub_err_t
+grub_cmd_fixvideo (grub_command_t cmd __attribute__ ((unused)),
+		   int argc __attribute__ ((unused)),
+		   char *argv[] __attribute__ ((unused)))
+{
+  grub_pci_iterate (scan_card);
+  return 0;
+}
+
+static grub_command_t cmd_fixvideo;
+
+GRUB_MOD_INIT(fixvideo)
+{
+  (void) mod;			/* To stop warning. */
+  cmd_fixvideo = grub_register_command ("fix_video", grub_cmd_fixvideo,
+					0, "Fix video problem.");
+
+}
+
+GRUB_MOD_FINI(fixvideo)
+{
+  grub_unregister_command (cmd_fixvideo);
+}
diff --git a/commands/efi/loadbios.c b/commands/efi/loadbios.c
new file mode 100644
index 0000000..d0a5a69
--- /dev/null
+++ b/commands/efi/loadbios.c
@@ -0,0 +1,211 @@
+/* loadbios.c - command to load a bios dump  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/file.h>
+#include <grub/efi/efi.h>
+#include <grub/pci.h>
+#include <grub/command.h>
+
+static grub_efi_guid_t acpi_guid = GRUB_EFI_ACPI_TABLE_GUID;
+static grub_efi_guid_t acpi2_guid = GRUB_EFI_ACPI_20_TABLE_GUID;
+static grub_efi_guid_t smbios_guid = GRUB_EFI_SMBIOS_TABLE_GUID;
+
+#define EBDA_SEG_ADDR	0x40e
+#define LOW_MEM_ADDR	0x413
+#define FAKE_EBDA_SEG	0x9fc0
+
+#define BLANK_MEM	0xffffffff
+#define VBIOS_ADDR	0xc0000
+#define SBIOS_ADDR	0xf0000
+
+static int
+enable_rom_area (void)
+{
+  grub_pci_address_t addr;
+  grub_uint32_t *rom_ptr;
+
+  rom_ptr = (grub_uint32_t *) VBIOS_ADDR;
+  if (*rom_ptr != BLANK_MEM)
+    {
+      grub_printf ("ROM image present.\n");
+      return 0;
+    }
+
+  addr = grub_pci_make_address (0, 0, 0, 36);
+  grub_pci_write_byte (addr++, 0x30);
+  grub_pci_write_byte (addr++, 0x33);
+  grub_pci_write_byte (addr++, 0x33);
+  grub_pci_write_byte (addr++, 0x33);
+  grub_pci_write_byte (addr++, 0x33);
+  grub_pci_write_byte (addr++, 0x33);
+  grub_pci_write_byte (addr++, 0x33);
+  grub_pci_write_byte (addr, 0);
+
+  *rom_ptr = 0;
+  if (*rom_ptr != 0)
+    {
+      grub_printf ("Can\'t enable rom area.\n");
+      return 0;
+    }
+
+  return 1;
+}
+
+static void
+lock_rom_area (void)
+{
+  grub_pci_address_t addr;
+
+  addr = grub_pci_make_address (0, 0, 0, 36);
+  grub_pci_write_byte (addr++, 0x10);
+  grub_pci_write_byte (addr++, 0x11);
+  grub_pci_write_byte (addr++, 0x11);
+  grub_pci_write_byte (addr++, 0x11);
+  grub_pci_write_byte (addr, 0x11);
+}
+
+static void
+fake_bios_data (int use_rom)
+{
+  unsigned i;
+  void *acpi, *smbios;
+  grub_uint16_t *ebda_seg_ptr, *low_mem_ptr;
+
+  ebda_seg_ptr = (grub_uint16_t *) EBDA_SEG_ADDR;
+  low_mem_ptr = (grub_uint16_t *) LOW_MEM_ADDR;
+  if ((*ebda_seg_ptr) || (*low_mem_ptr))
+    return;
+
+  acpi = 0;
+  smbios = 0;
+  for (i = 0; i < grub_efi_system_table->num_table_entries; i++)
+    {
+      grub_efi_guid_t *guid =
+	&grub_efi_system_table->configuration_table[i].vendor_guid;
+
+      if (! grub_memcmp (guid, &acpi2_guid, sizeof (grub_efi_guid_t)))
+	{
+	  acpi = grub_efi_system_table->configuration_table[i].vendor_table;
+	  grub_printf ("ACPI2: %p\n", acpi);
+	}
+      else if (! grub_memcmp (guid, &acpi_guid, sizeof (grub_efi_guid_t)))
+	{
+	  void *t;
+
+	  t = grub_efi_system_table->configuration_table[i].vendor_table;
+	  if (! acpi)
+	    acpi = t;
+	  grub_printf ("ACPI: %p\n", t);
+	}
+      else if (! grub_memcmp (guid, &smbios_guid, sizeof (grub_efi_guid_t)))
+	{
+	  smbios = grub_efi_system_table->configuration_table[i].vendor_table;
+	  grub_printf ("SMBIOS: %p\n", smbios);
+	}
+    }
+
+
+  *ebda_seg_ptr = FAKE_EBDA_SEG;
+  *low_mem_ptr = (FAKE_EBDA_SEG >> 6);
+
+  if (acpi)
+    grub_memcpy ((char *) (FAKE_EBDA_SEG << 4), acpi, 1024);
+
+  if ((use_rom) && (smbios))
+    grub_memcpy ((char *) SBIOS_ADDR, (char *) smbios + 16, 16);
+}
+
+static grub_err_t
+grub_cmd_fakebios (struct grub_command *cmd __attribute__ ((unused)),
+		   int argc __attribute__ ((unused)),
+		   char *argv[] __attribute__ ((unused)))
+{
+  if (enable_rom_area ())
+    {
+      fake_bios_data (1);
+      lock_rom_area ();
+    }
+  else
+    fake_bios_data (0);
+}
+
+static grub_err_t
+grub_cmd_loadbios (grub_command_t cmd __attribute__ ((unused)),
+		   int argc, char *argv[])
+{
+  grub_file_t file;
+  int size;
+
+  if (argc == 0)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "No rom image specified");
+
+  if (argc > 1)
+    {
+      file = grub_file_open (argv[1]);
+      if (! file)
+	return grub_errno;
+
+      if (file->size != 4)
+	grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid int10 dump size");
+      else
+	grub_file_read (file, (char *) 0x40, 4);
+
+      grub_file_close (file);
+      if (grub_errno)
+	return grub_errno;
+    }
+
+  file = grub_file_open (argv[0]);
+  if (! file)
+    return grub_errno;
+
+  size = file->size;
+  if ((size < 0x10000) || (size > 0x40000))
+    grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid bios dump size");
+  else if (enable_rom_area ())
+    {
+      grub_file_read (file, (char *) VBIOS_ADDR, size);
+      fake_bios_data (size <= 0x40000);
+      lock_rom_area ();
+    }
+
+  grub_file_close (file);
+  return grub_errno;
+}
+
+static grub_command_t cmd_fakebios, cmd_loadbios;
+
+GRUB_MOD_INIT(loadbios)
+{
+  (void) mod;			/* To stop warning. */
+  cmd_fakebios = grub_register_command ("fakebios", grub_cmd_fakebios,
+					0, "fake bios.");
+
+  cmd_loadbios = grub_register_command ("loadbios", grub_cmd_loadbios,
+					"loadbios BIOS_DUMP [INT10_DUMP]",
+					"Load bios dump.");
+}
+
+GRUB_MOD_FINI(loadbios)
+{
+  grub_unregister_command (cmd_fakebios);
+  grub_unregister_command (cmd_loadbios);
+}
diff --git a/commands/memrw.c b/commands/memrw.c
new file mode 100644
index 0000000..fa04c76
--- /dev/null
+++ b/commands/memrw.c
@@ -0,0 +1,101 @@
+/* memrw.c - command to read / write physical memory  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/command.h>
+
+static grub_command_t cmd_read_byte, cmd_read_word, cmd_read_dword;
+static grub_command_t cmd_write_byte, cmd_write_word, cmd_write_dword;
+
+static grub_err_t
+grub_cmd_read (grub_command_t cmd, int argc, char **argv)
+{
+  grub_target_addr_t addr;
+  grub_uint32_t value;
+
+  if (argc != 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid number of arguments");
+
+  addr = grub_strtoul (argv[0], 0, 0);
+  if (cmd->name[5] == 'd')
+    value = *((grub_uint32_t *) addr);
+  else if (cmd->name[5] == 'w')
+    value = *((grub_uint16_t *) addr);
+  else
+    value = *((grub_uint8_t *) addr);
+
+  grub_printf ("0x%x\n", value);
+
+  return 0;
+}
+
+static grub_err_t
+grub_cmd_write (grub_command_t cmd, int argc, char **argv)
+{
+  grub_target_addr_t addr;
+  grub_uint32_t value;
+
+  if (argc != 2)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid number of arguments");
+
+  addr = grub_strtoul (argv[0], 0, 0);
+  value = grub_strtoul (argv[1], 0, 0);
+  if (cmd->name[6] == 'd')
+    *((grub_uint32_t *) addr) = value;
+  else if (cmd->name[6] == 'w')
+    *((grub_uint16_t *) addr) = (grub_uint16_t) value;
+  else
+    *((grub_uint8_t *) addr) = (grub_uint8_t) value;
+
+  return 0;
+}
+
+GRUB_MOD_INIT(memrw)
+{
+  (void) mod;			/* To stop warning. */
+  cmd_read_byte =
+    grub_register_command ("read_byte", grub_cmd_read,
+			   "read_byte ADDR", "read byte.");
+  cmd_read_word =
+    grub_register_command ("read_word", grub_cmd_read,
+			   "read_word ADDR", "read word.");
+  cmd_read_dword =
+    grub_register_command ("read_dword", grub_cmd_read,
+			   "read_dword ADDR", "read dword.");
+  cmd_write_byte =
+    grub_register_command ("write_byte", grub_cmd_write,
+			   "write_byte ADDR VALUE", "write byte.");
+  cmd_write_word =
+    grub_register_command ("write_word", grub_cmd_write,
+			   "write_word ADDR VALUE", "write word.");
+  cmd_write_dword =
+    grub_register_command ("write_dword", grub_cmd_write,
+			   "write_dword ADDR VALUE", "write dword.");
+}
+
+GRUB_MOD_FINI(memrw)
+{
+  grub_unregister_command (cmd_read_byte);
+  grub_unregister_command (cmd_read_word);
+  grub_unregister_command (cmd_read_dword);
+  grub_unregister_command (cmd_write_byte);
+  grub_unregister_command (cmd_write_word);
+  grub_unregister_command (cmd_write_dword);
+}
diff --git a/conf/common.rmk b/conf/common.rmk
index 43bc683..ffe4ea2 100644
--- a/conf/common.rmk
+++ b/conf/common.rmk
@@ -155,6 +155,12 @@ CLEANFILES += $(grub-mkconfig_SCRIPTS)
 
 grub-mkconfig_DATA += util/grub.d/README
 
+# For grub-dumpbios
+grub-dumpbios: util/grub-dumpbios.in config.status
+	./config.status --file=$@:$<
+	chmod +x $@
+sbin_SCRIPTS += grub-dumpbios
+CLEANFILES += grub-dumpbios
 
 # Filing systems.
 pkglib_MODULES += fshelp.mod fat.mod ufs.mod ext2.mod ntfs.mod		\
@@ -335,7 +341,7 @@ pkglib_MODULES += minicmd.mod extcmd.mod hello.mod handler.mod	\
 	 ls.mod	cmp.mod cat.mod help.mod search.mod		\
 	loopback.mod fs_uuid.mod configfile.mod echo.mod	\
 	terminfo.mod test.mod blocklist.mod hexdump.mod		\
-	read.mod sleep.mod loadenv.mod crc.mod
+	read.mod sleep.mod loadenv.mod crc.mod memrw.mod
 
 # For minicmd.mod.
 minicmd_mod_SOURCES = commands/minicmd.c
@@ -442,6 +448,11 @@ crc_mod_SOURCES = commands/crc.c lib/crc.c
 crc_mod_CFLAGS = $(COMMON_CFLAGS)
 crc_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For memrw.mod.
+memrw_mod_SOURCES = commands/memrw.c
+memrw_mod_CFLAGS = $(COMMON_CFLAGS)
+memrw_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 # Common Video Subsystem specific modules.
 pkglib_MODULES += video.mod videotest.mod bitmap.mod tga.mod jpeg.mod	\
 	png.mod	font.mod gfxterm.mod
diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk
index 18a99df..e250304 100644
--- a/conf/i386-efi.rmk
+++ b/conf/i386-efi.rmk
@@ -79,7 +79,7 @@ grub_install_SOURCES = util/i386/efi/grub-install.in
 # Modules.
 pkglib_MODULES = kernel.mod normal.mod chain.mod appleldr.mod \
 	linux.mod halt.mod reboot.mod pci.mod lspci.mod \
-	datetime.mod date.mod datehook.mod
+	datetime.mod date.mod datehook.mod loadbios.mod fixvideo.mod
 
 # For kernel.mod.
 kernel_mod_EXPORTS = no
@@ -182,5 +182,15 @@ datehook_mod_SOURCES = hook/datehook.c
 datehook_mod_CFLAGS = $(COMMON_CFLAGS)
 datehook_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For loadbios.mod
+loadbios_mod_SOURCES = commands/efi/loadbios.c
+loadbios_mod_CFLAGS = $(COMMON_CFLAGS)
+loadbios_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For fixvideo.mod
+fixvideo_mod_SOURCES = commands/efi/fixvideo.c
+fixvideo_mod_CFLAGS = $(COMMON_CFLAGS)
+fixvideo_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 include $(srcdir)/conf/i386.mk
 include $(srcdir)/conf/common.mk
diff --git a/conf/x86_64-efi.rmk b/conf/x86_64-efi.rmk
index faa59fb..ec246ed 100644
--- a/conf/x86_64-efi.rmk
+++ b/conf/x86_64-efi.rmk
@@ -81,7 +81,7 @@ grub_install_SOURCES = util/i386/efi/grub-install.in
 # Modules.
 pkglib_MODULES = kernel.mod normal.mod chain.mod appleldr.mod \
 	halt.mod reboot.mod linux.mod pci.mod lspci.mod \
-	datetime.mod date.mod datehook.mod
+	datetime.mod date.mod datehook.mod loadbios.mod fixvideo.mod
 
 # For kernel.mod.
 kernel_mod_EXPORTS = no
@@ -185,5 +185,15 @@ datehook_mod_SOURCES = hook/datehook.c
 datehook_mod_CFLAGS = $(COMMON_CFLAGS)
 datehook_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For loadbios.mod
+loadbios_mod_SOURCES = commands/efi/loadbios.c
+loadbios_mod_CFLAGS = $(COMMON_CFLAGS)
+loadbios_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For fixvideo.mod
+fixvideo_mod_SOURCES = commands/efi/fixvideo.c
+fixvideo_mod_CFLAGS = $(COMMON_CFLAGS)
+fixvideo_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 include $(srcdir)/conf/i386.mk
 include $(srcdir)/conf/common.mk
diff --git a/include/grub/i386/pci.h b/include/grub/i386/pci.h
index f4f08ab..996f642 100644
--- a/include/grub/i386/pci.h
+++ b/include/grub/i386/pci.h
@@ -32,4 +32,39 @@ grub_pci_read (grub_pci_address_t addr)
   return grub_inl (GRUB_PCI_DATA_REG);
 }
 
+static inline grub_uint16_t
+grub_pci_read_word (grub_pci_address_t addr)
+{
+  grub_outl (addr & ~3, GRUB_PCI_ADDR_REG);
+  return grub_inw (GRUB_PCI_DATA_REG + (addr & 3));
+}
+
+static inline grub_uint8_t
+grub_pci_read_byte (grub_pci_address_t addr)
+{
+  grub_outl (addr & ~3, GRUB_PCI_ADDR_REG);
+  return grub_inb (GRUB_PCI_DATA_REG + (addr & 3));
+}
+
+static inline void
+grub_pci_write (grub_pci_address_t addr, grub_uint32_t data)
+{
+  grub_outl (addr, GRUB_PCI_ADDR_REG);
+  grub_outl (data, GRUB_PCI_DATA_REG);
+}
+
+static inline void
+grub_pci_write_word (grub_pci_address_t addr, grub_uint16_t data)
+{
+  grub_outl (addr & ~3, GRUB_PCI_ADDR_REG);
+  grub_outw (data, GRUB_PCI_DATA_REG + (addr & 3));
+}
+
+static inline void
+grub_pci_write_byte (grub_pci_address_t addr, grub_uint8_t data)
+{
+  grub_outl (addr & ~3, GRUB_PCI_ADDR_REG);
+  grub_outb (data, GRUB_PCI_DATA_REG + (addr & 3));
+}
+
 #endif /* GRUB_CPU_PCI_H */
diff --git a/include/grub/pci.h b/include/grub/pci.h
index aceee49..7c8b505 100644
--- a/include/grub/pci.h
+++ b/include/grub/pci.h
@@ -36,8 +36,8 @@
 #define  GRUB_PCI_ADDR_IO_MASK		~0x03
 
 typedef grub_uint32_t grub_pci_id_t;
-typedef int (*grub_pci_iteratefunc_t) (int bus, int device, int func,
-				       grub_pci_id_t pciid);
+typedef int NESTED_FUNC_ATTR (*grub_pci_iteratefunc_t)
+     (int bus, int device, int func, grub_pci_id_t pciid);
 typedef grub_uint32_t grub_pci_address_t;
 
 grub_pci_address_t EXPORT_FUNC(grub_pci_make_address) (int bus, int device,
diff --git a/loader/i386/efi/linux.c b/loader/i386/efi/linux.c
index c62198a..fa83cac 100644
--- a/loader/i386/efi/linux.c
+++ b/loader/i386/efi/linux.c
@@ -30,6 +30,7 @@
 #include <grub/efi/api.h>
 #include <grub/efi/efi.h>
 #include <grub/efi/uga_draw.h>
+#include <grub/pci.h>
 #include <grub/command.h>
 
 #define GRUB_LINUX_CL_OFFSET		0x1000
@@ -248,9 +249,9 @@ allocate_pages (grub_size_t prot_size)
     }
 
   grub_dprintf ("linux", "real_mode_mem = %lx, real_mode_pages = %x, "
-                "prot_mode_mem = %lx, prot_mode_pages = %x\n",
-                (unsigned long) real_mode_mem, (unsigned) real_mode_pages,
-                (unsigned long) prot_mode_mem, (unsigned) prot_mode_pages);
+		"prot_mode_mem = %lx, prot_mode_pages = %x\n",
+		(unsigned long) real_mode_mem, (unsigned) real_mode_pages,
+		(unsigned long) prot_mode_mem, (unsigned) prot_mode_pages);
 
   grub_free (mmap);
   return 1;
@@ -263,8 +264,8 @@ allocate_pages (grub_size_t prot_size)
 
 static void
 grub_e820_add_region (struct grub_e820_mmap *e820_map, int *e820_num,
-                      grub_uint64_t start, grub_uint64_t size,
-                      grub_uint32_t type)
+		      grub_uint64_t start, grub_uint64_t size,
+		      grub_uint32_t type)
 {
   int n = *e820_num;
 
@@ -283,57 +284,6 @@ grub_e820_add_region (struct grub_e820_mmap *e820_map, int *e820_num,
     }
 }
 
-static grub_efi_guid_t acpi_guid = GRUB_EFI_ACPI_TABLE_GUID;
-static grub_efi_guid_t acpi2_guid = GRUB_EFI_ACPI_20_TABLE_GUID;
-
-#define EBDA_SEG_ADDR	0x40e
-#define LOW_MEM_ADDR	0x413
-#define FAKE_EBDA_SEG	0x9fc0
-
-static void
-fake_bios_data (void)
-{
-  unsigned i;
-  void *acpi;
-  grub_uint16_t *ebda_seg_ptr, *low_mem_ptr;
-
-  acpi = 0;
-  for (i = 0; i < grub_efi_system_table->num_table_entries; i++)
-    {
-      grub_efi_guid_t *guid =
-	&grub_efi_system_table->configuration_table[i].vendor_guid;
-
-      if (! grub_memcmp (guid, &acpi2_guid, sizeof (grub_efi_guid_t)))
-	{
-	  acpi = grub_efi_system_table->configuration_table[i].vendor_table;
-	  grub_printf ("ACPI2: %p\n", acpi);
-	}
-      else if (! grub_memcmp (guid, &acpi_guid, sizeof (grub_efi_guid_t)))
-	{
-	  void *t;
-
-	  t = grub_efi_system_table->configuration_table[i].vendor_table;
-	  if (! acpi)
-	    acpi = t;
-	  grub_printf ("ACPI: %p\n", t);
-	}
-    }
-
-  if (acpi == 0)
-    return;
-
-  ebda_seg_ptr = (grub_uint16_t *) EBDA_SEG_ADDR;
-  low_mem_ptr = (grub_uint16_t *) LOW_MEM_ADDR;
-
-  if ((*ebda_seg_ptr) || (*low_mem_ptr))
-    return;
-
-  *ebda_seg_ptr = FAKE_EBDA_SEG;
-  *low_mem_ptr = FAKE_EBDA_SEG >> 6;
-
-  grub_memcpy ((char *) (FAKE_EBDA_SEG << 4), acpi, 1024);
-}
-
 #ifdef __x86_64__
 struct
 {
@@ -353,13 +303,11 @@ grub_linux_boot (void)
   grub_efi_memory_descriptor_t *desc;
   int e820_num;
   
-  fake_bios_data ();
-
   params = real_mode_mem;
 
   grub_dprintf ("linux", "code32_start = %x, idt_desc = %lx, gdt_desc = %lx\n",
 		(unsigned) params->code32_start,
-                (unsigned long) &(idt_desc.limit),
+		(unsigned long) &(idt_desc.limit),
 		(unsigned long) &(gdt_desc.limit));
   grub_dprintf ("linux", "idt = %x:%lx, gdt = %x:%lx\n",
 		(unsigned) idt_desc.limit, (unsigned long) idt_desc.base,
@@ -376,69 +324,69 @@ grub_linux_boot (void)
        desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
     {
       switch (desc->type)
-        {
-        case GRUB_EFI_ACPI_RECLAIM_MEMORY:
-          grub_e820_add_region (params->e820_map, &e820_num,
-                                desc->physical_start,
-                                desc->num_pages << 12,
-                                GRUB_E820_ACPI);
-          break;
-
-        case GRUB_EFI_ACPI_MEMORY_NVS:
-          grub_e820_add_region (params->e820_map, &e820_num,
-                                desc->physical_start,
-                                desc->num_pages << 12,
-                                GRUB_E820_NVS);
-          break;
-
-        case GRUB_EFI_RUNTIME_SERVICES_CODE:
-          grub_e820_add_region (params->e820_map, &e820_num,
-                                desc->physical_start,
-                                desc->num_pages << 12,
-                                GRUB_E820_EXEC_CODE);
-          break;
-
-        case GRUB_EFI_LOADER_CODE:
-        case GRUB_EFI_LOADER_DATA:
-        case GRUB_EFI_BOOT_SERVICES_CODE:
-        case GRUB_EFI_BOOT_SERVICES_DATA:
-        case GRUB_EFI_CONVENTIONAL_MEMORY:
-          {
-            grub_uint64_t start, size, end;
-
-            start = desc->physical_start;
-            size = desc->num_pages << 12;
-            end = start + size;
-
-            /* Skip A0000 - 100000 region.  */
-            if ((start < 0x100000ULL) && (end > 0xA0000ULL))
-              {
-                if (start < 0xA0000ULL)
-                  {
-                    grub_e820_add_region (params->e820_map, &e820_num,
-                                          start,
-                                          0xA0000ULL - start,
-                                          GRUB_E820_RAM);
-                  }
-
-                if (end <= 0x100000ULL)
-                  continue;
-
-                start = 0x100000ULL;
-                size = end - start;
-              }
-
-            grub_e820_add_region (params->e820_map, &e820_num,
-                                  start, size, GRUB_E820_RAM);
-            break;
-          }
-
-        default:
-          grub_e820_add_region (params->e820_map, &e820_num,
-                                desc->physical_start,
-                                desc->num_pages << 12,
-                                GRUB_E820_RESERVED);
-        }
+	{
+	case GRUB_EFI_ACPI_RECLAIM_MEMORY:
+	  grub_e820_add_region (params->e820_map, &e820_num,
+				desc->physical_start,
+				desc->num_pages << 12,
+				GRUB_E820_ACPI);
+	  break;
+
+	case GRUB_EFI_ACPI_MEMORY_NVS:
+	  grub_e820_add_region (params->e820_map, &e820_num,
+				desc->physical_start,
+				desc->num_pages << 12,
+				GRUB_E820_NVS);
+	  break;
+
+	case GRUB_EFI_RUNTIME_SERVICES_CODE:
+	  grub_e820_add_region (params->e820_map, &e820_num,
+				desc->physical_start,
+				desc->num_pages << 12,
+				GRUB_E820_EXEC_CODE);
+	  break;
+
+	case GRUB_EFI_LOADER_CODE:
+	case GRUB_EFI_LOADER_DATA:
+	case GRUB_EFI_BOOT_SERVICES_CODE:
+	case GRUB_EFI_BOOT_SERVICES_DATA:
+	case GRUB_EFI_CONVENTIONAL_MEMORY:
+	  {
+	    grub_uint64_t start, size, end;
+
+	    start = desc->physical_start;
+	    size = desc->num_pages << 12;
+	    end = start + size;
+
+	    /* Skip A0000 - 100000 region.  */
+	    if ((start < 0x100000ULL) && (end > 0xA0000ULL))
+	      {
+		if (start < 0xA0000ULL)
+		  {
+		    grub_e820_add_region (params->e820_map, &e820_num,
+					  start,
+					  0xA0000ULL - start,
+					  GRUB_E820_RAM);
+		  }
+
+		if (end <= 0x100000ULL)
+		  continue;
+
+		start = 0x100000ULL;
+		size = end - start;
+	      }
+
+	    grub_e820_add_region (params->e820_map, &e820_num,
+				  start, size, GRUB_E820_RAM);
+	    break;
+	  }
+
+	default:
+	  grub_e820_add_region (params->e820_map, &e820_num,
+				desc->physical_start,
+				desc->num_pages << 12,
+				GRUB_E820_RESERVED);
+	}
     }
 
   params->mmap_size = e820_num;
@@ -520,41 +468,105 @@ static grub_efi_guid_t uga_draw_guid = GRUB_EFI_UGA_DRAW_GUID;
 #define FBTEST_STEP	(0x10000 >> 2)
 #define FBTEST_COUNT	8
 
-static grub_uint32_t fb_list[]=
-  {0x40000000, 0x80000000, 0xc0000000, 0};
+static int
+find_line_len (grub_uint32_t *fb_base, grub_uint32_t *line_len)
+{
+  grub_uint32_t *base = (grub_uint32_t *) (grub_target_addr_t) *fb_base;
+  int i;
+
+  for (i = 0; i < FBTEST_COUNT; i++, base += FBTEST_STEP)
+    {
+      if ((*base & RGB_MASK) == RGB_MAGIC)
+	{
+	  int j;
+
+	  for (j = LINE_MIN; j <= LINE_MAX; j++)
+	    {
+	      if ((base[j] & RGB_MASK) == RGB_MAGIC)
+		{
+		  *fb_base = (grub_uint32_t) (grub_target_addr_t) base;
+		  *line_len = j << 2;
+
+		  return 1;
+		}
+	    }
+
+	  break;
+	}
+    }
+
+  return 0;
+}
 
 static int
 find_framebuf (grub_uint32_t *fb_base, grub_uint32_t *line_len)
 {
-  grub_uint32_t *fb;
+  int found = 0;
+
+  auto int NESTED_FUNC_ATTR find_card (int bus, int dev, int func,
+				       grub_pci_id_t pciid);
 
-  for (fb = fb_list; *fb; fb++)
+  int NESTED_FUNC_ATTR find_card (int bus, int dev, int func,
+				  grub_pci_id_t pciid __attribute__ ((unused)))
     {
-      grub_uint32_t *base = (grub_uint32_t *) (grub_target_addr_t) *fb;
-      int i;
+      grub_pci_address_t addr;
 
-      for (i = 0; i < FBTEST_COUNT; i++, base += FBTEST_STEP)
-        {
-	  if ((*base & RGB_MASK) == RGB_MAGIC)
+      addr = grub_pci_make_address (bus, dev, func, 2);
+      if (grub_pci_read (addr) >> 24 == 0x3)
+	{
+	  int i;
+
+	  grub_printf ("Display controller: %d:%d.%d\n", bus, dev, func);
+	  addr += 8;
+	  for (i = 0; i < 6; i++, addr += 4)
 	    {
-	      int j;
-
-	      for (j = LINE_MIN; j <= LINE_MAX; j++)
-            {
-		  if ((base[j] & RGB_MASK) == RGB_MAGIC)
-                {
-		      *fb_base = (grub_uint32_t) (grub_target_addr_t) base;
-		      *line_len = j << 2;
-
-		      return 0;
-                }
-            }
-
-                break;
-            }
-        }
+	      grub_uint32_t old_bar1, old_bar2, type;
+	      grub_uint64_t base64;
+
+	      old_bar1 = grub_pci_read (addr);
+	      if ((! old_bar1) || (old_bar1 & GRUB_PCI_ADDR_SPACE_IO))
+		continue;
+
+	      type = old_bar1 & GRUB_PCI_ADDR_MEM_TYPE_MASK;
+	      if (type == GRUB_PCI_ADDR_MEM_TYPE_64)
+		{
+		  if (i == 5)
+		    break;
+
+		  old_bar2 = grub_pci_read (addr + 4);
+		}
+	      else
+		old_bar2 = 0;
+
+	      base64 = old_bar2;
+	      base64 <<= 32;
+	      base64 |= (old_bar1 & GRUB_PCI_ADDR_MEM_MASK);
+
+	      grub_printf ("%s(%d): 0x%llx\n",
+			   ((old_bar1 & GRUB_PCI_ADDR_MEM_PREFETCH) ?
+			    "VMEM" : "MMIO"), i,
+			   (unsigned long long) base64);
+
+	      if ((old_bar1 & GRUB_PCI_ADDR_MEM_PREFETCH) && (! found))
+		{
+		  *fb_base = base64;
+		  if (find_line_len (fb_base, line_len))
+		    found++;
+		}
+
+	      if (type == GRUB_PCI_ADDR_MEM_TYPE_64)
+		{
+		  i++;
+		  addr += 4;
+		}
+	    }
+	}
+
+      return found;
     }
-  return 1;
+
+  grub_pci_iterate (find_card);
+  return found;
 }
 
 static int
@@ -580,13 +592,13 @@ grub_linux_setup_video (struct linux_kernel_params *params)
   ret = find_framebuf (&fb_base, &line_len);
   grub_efi_set_text_mode (1);
 
-  if (ret)
+  if (! ret)
     {
       grub_printf ("Can\'t find frame buffer address\n");
       return 1;
     }
 
-  grub_printf ("Video frame buffer: 0x%x\n", fb_base);
+  grub_printf ("Frame buffer base: 0x%x\n", fb_base);
   grub_printf ("Video line length: %d\n", line_len);
 
   params->lfb_width = width;
@@ -606,6 +618,9 @@ grub_linux_setup_video (struct linux_kernel_params *params)
   params->reserved_mask_size = 8;
   params->reserved_field_pos = 24;
 
+  params->have_vga = GRUB_VIDEO_TYPE_VLFB;
+  params->vid_mode = 0x338;  /* 1024x768x32  */
+
   return 0;
 }
 
@@ -621,7 +636,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
   grub_ssize_t len;
   int i;
   char *dest;
-  int video_type;
 
   grub_dl_ref (my_mod);
   
@@ -808,9 +822,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
   grub_printf ("   [Linux-bzImage, setup=0x%x, size=0x%x]\n",
 	       (unsigned) real_size, (unsigned) prot_size);
 
+  grub_linux_setup_video (params);
+
   /* Detect explicitly specified memory size, if any.  */
   linux_mem_size = 0;
-  video_type = 0;
   for (i = 1; i < argc; i++)
     if (grub_memcmp (argv[i], "mem=", 4) == 0)
       {
@@ -846,20 +861,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
 	      linux_mem_size <<= shift;
 	  }
       }
-    else if (grub_memcmp (argv[i], "video=", 6) == 0)
+    else if (grub_memcmp (argv[i], "video=efifb", 11) == 0)
       {
-        if (grub_memcmp (&argv[i][6], "vesafb", 6) == 0)
-          video_type = GRUB_VIDEO_TYPE_VLFB;
-        else if (grub_memcmp (&argv[i][6], "efifb", 5) == 0)
-          video_type = GRUB_VIDEO_TYPE_EFI;
+	if (params->have_vga)
+	  params->have_vga = GRUB_VIDEO_TYPE_EFI;
       }
 
-  if (video_type)
-    {
-      if (!  grub_linux_setup_video (params))
-        params->have_vga = video_type;
-    }
-
   /* Specify the boot file.  */
   dest = grub_stpcpy ((char *) real_mode_mem + GRUB_LINUX_CL_OFFSET,
 		      "BOOT_IMAGE=");
@@ -946,7 +953,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
 
   /* Usually, the compression ratio is about 50%.  */
   addr_min = (grub_addr_t) prot_mode_mem + ((prot_mode_pages * 3) << 12)
-             + page_align (size);
+	     + page_align (size);
   
   /* Find the highest address to put the initrd.  */
   mmap_size = find_mmap_size ();
@@ -968,7 +975,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
 	    physical_end = addr_max;
 
 	  if (physical_end < page_align (size))
-            continue;
+	    continue;
 
 	  physical_end -= page_align (size);
 
diff --git a/util/grub-dumpbios.in b/util/grub-dumpbios.in
new file mode 100644
index 0000000..3965039
--- /dev/null
+++ b/util/grub-dumpbios.in
@@ -0,0 +1,58 @@
+#! /bin/sh
+#
+# Copyright (C) 2009  Free Software Foundation, Inc.
+#
+# GRUB is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# GRUB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+
+# Usage: usage
+# Print the usage.
+usage () {
+    cat <<EOF
+Usage: $0 [OPTION]
+Create vbios and int10 dump
+
+  -o, --output=DIR        set output directory
+  -h, --help              print this message and exit
+  -v, --version           print the version information and exit
+
+Report bugs to <bug-g...@gnu.org>.
+EOF
+}
+
+# Check the arguments.
+for option in "$@"; do
+    case "$option" in
+    -h | --help)
+	usage
+	exit 0 ;;
+    -v | --version)
+	echo "$0 (GNU GRUB @PACKAGE_VERSION@)"
+	exit 0 ;;
+    -o)
+	shift
+	output_dir=$1
+	;;
+    --output=)
+	output_dir=`echo "$option" | sed 's/--output=//'`
+	;;
+    -*)
+	echo "Unrecognized option \`$option'" 1>&2
+	usage
+	exit 1
+	;;
+    esac
+done
+
+dd if=/dev/mem of=${output_dir}vbios.bin bs=65536 skip=12 count=1
+dd if=/dev/mem of=${output_dir}int10.bin bs=4 skip=16 count=1
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to