* [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
* Re: [PATCH] Emulate the bios area in efi linux loader
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
0 siblings, 1 reply; 4+ messages in thread
From: phcoder @ 2009-02-27 15:02 UTC (permalink / raw)
To: The development of GRUB 2
> 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.
In my efiemu I have a code which does exactly the opposite. But
additionally it allows the user to replace/add/remove ACPI tables.
Perhaps we can share the code and make it also works in cases like
replacing some of ACPI tables on pc then putting new rsdp pointer to
EBDA, replacing some tables on efi system then using EBDA, modyfiing
acpi on efi and putting bew rsdp back to efi and so on.
--
Regards
Vladimir 'phcoder' Serbinenko
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] Emulate the bios area in efi linux loader
2009-02-27 15:02 ` phcoder
@ 2009-03-01 12:11 ` Bean
2009-03-01 18:00 ` Bean
0 siblings, 1 reply; 4+ messages in thread
From: Bean @ 2009-03-01 12:11 UTC (permalink / raw)
To: The development of GRUB 2
[-- Attachment #1: Type: text/plain, Size: 62 bytes --]
Hi,
This is an update patch, it checks ACPI 1 & 2.
--
Bean
[-- Attachment #2: efi_3.diff --]
[-- Type: application/octet-stream, Size: 3071 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..d2ab6f5 100644
--- a/loader/i386/efi/linux.c
+++ b/loader/i386/efi/linux.c
@@ -283,6 +283,57 @@ 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
{
@@ -302,6 +353,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",
@@ -522,8 +575,8 @@ grub_linux_setup_video (struct linux_kernel_params *params)
grub_efi_set_text_mode (0);
pixel = RGB_MAGIC;
- efi_call_10 (c->blt, c, &pixel, GRUB_EFI_UGA_VIDEO_FILL,
- 0, 0, 0, 0, 1, height, 0);
+ efi_call_10 (c->blt, c, (struct grub_efi_uga_pixel *) &pixel,
+ GRUB_EFI_UGA_VIDEO_FILL, 0, 0, 0, 0, 1, height, 0);
ret = find_framebuf (&fb_base, &line_len);
grub_efi_set_text_mode (1);
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] Emulate the bios area in efi linux loader
2009-03-01 12:11 ` Bean
@ 2009-03-01 18:00 ` Bean
0 siblings, 0 replies; 4+ messages in thread
From: Bean @ 2009-03-01 18:00 UTC (permalink / raw)
To: The development of GRUB 2
On Sun, Mar 1, 2009 at 8:11 PM, Bean <bean123ch@gmail.com> wrote:
> Hi,
>
> This is an update patch, it checks ACPI 1 & 2.
Hi,
I'm getting good test result from the ubuntu forum. With this patch,
it's able to boot 2.6.26-28 686/amd64 linux kernel from 32-bit/64-bit
firmware.
Committed.
--
Bean
^ permalink raw reply [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.