All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Emulate the bios area in efi linux loader
@ 2009-02-27 12:52 Bean
  2009-02-27 15:02 ` phcoder
  0 siblings, 1 reply; 4+ messages in thread
From: Bean @ 2009-02-27 12:52 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 1419 bytes --]

Hi,

Linux needs to locate important data structure such as ACPI. In normal
EFI booting, these information can be retrieved from efi system table,
However, in case of cross booting, for example, booting 32-bit kernel
from 64-bit firmware, or vice verse, the efi information is not
usable, which leads to dead keyboard and the hda timeout problem.

Moreover, in kernel 2.6.27 and above, linux only map RAM, and efi
runtime area need to be mapped with efi_ioremap. However, efi_ioremap
only reserve MAX_EFI_IO_PAGES (100) pages for efi, which is not enough
for apple 64-bit firmware (about 17m). Until this is fixed, we need to
pass "noefi" option to avoid hanging at startup. But this would lead
to similar problem as cross booting.

This patch copy the ACPI information to conventional memory and
emulated the extended bios data area. With this, linux can find
information about ACPI even if efi information is not available, thus
resolving the above problem.

2009-02-27  Bean  <bean123ch@gmail.com>

	* include/grub/efi/api.h (GRUB_EFI_MPS_TABALE_GUID): New constant.
	(GRUB_EFI_ACPI_TABLE_GUID): Likewise.
	(GRUB_EFI_ACPI_20_TABLE_GUID): Likewise.
	(GRUB_EFI_SMBIOS_TABLE_GUID): Likewise.

	* loader/i386/efi/linux.c (acpi2_guid): New variable.
	(EBDA_SEG_ADDR): New constant.
	(LOW_MEM_ADDR): Likewise.
	(FAKE_EBDA_SEG): Likewise.
	(fake_bios_data): New function.
	(grub_linux_boot): Call fake_bios_data.

-- 
Bean

[-- Attachment #2: efi_2.diff --]
[-- Type: application/octet-stream, Size: 2344 bytes --]

diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
index 50556bf..1a56554 100644
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -88,6 +88,26 @@
     { 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
   }
 
+#define GRUB_EFI_MPS_TABLE_GUID	\
+  { 0xeb9d2d2f, 0x2d88, 0x11d3, \
+    { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
+  }
+
+#define GRUB_EFI_ACPI_TABLE_GUID	\
+  { 0xeb9d2d30, 0x2d88, 0x11d3, \
+    { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
+  }
+
+#define GRUB_EFI_ACPI_20_TABLE_GUID	\
+  { 0x8868e871, 0xe4f1, 0x11d3, \
+    { 0xbc, 0x22, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \
+  }
+
+#define GRUB_EFI_SMBIOS_TABLE_GUID	\
+  { 0xeb9d2d31, 0x2d88, 0x11d3, \
+    { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
+  }
+
 /* Enumerations.  */
 enum grub_efi_timer_delay
   {
diff --git a/loader/i386/efi/linux.c b/loader/i386/efi/linux.c
index 4528c21..e9a147c 100644
--- a/loader/i386/efi/linux.c
+++ b/loader/i386/efi/linux.c
@@ -283,6 +283,47 @@ grub_e820_add_region (struct grub_e820_mmap *e820_map, int *e820_num,
     }
 }
 
+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 *acpi2;
+  grub_uint16_t *ebda_seg_ptr, *low_mem_ptr;
+
+  acpi2 = 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)))
+	{
+	  acpi2 = grub_efi_system_table->configuration_table[i].vendor_table;
+	  grub_printf ("ACPI2: %p\n", acpi2);
+	}
+    }
+
+  if (acpi2 == 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), acpi2, 256);
+}
+
 #ifdef __x86_64__
 struct
 {
@@ -302,6 +343,8 @@ 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",

^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2009-03-01 18:00 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-02-27 12:52 [PATCH] Emulate the bios area in efi linux loader Bean
2009-02-27 15:02 ` phcoder
2009-03-01 12:11   ` Bean
2009-03-01 18:00     ` Bean

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.