diff --git a/ChangeLog b/ChangeLog index 2a7889bf7..0f9b33a82 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2010-09-22 Vladimir Serbinenko + + Implement EFI and ACPI multiboot2 extensions. + + * grub-core/loader/multiboot_mbi2.c (grub_multiboot_load): Declare + new tags as supported. + (acpiv2_size): New function. + (grub_multiboot_get_mbi_size): Take new tags into account. + (grub_multiboot_make_mbi): Add new tags. + * include/grub/multiboot.h (GRUB_MACHINE_HAS_ACPI): New definition. + 2010-09-21 Aleš Nesrsta * grub-core/bus/usb/serial/common.c (grub_usbserial_attach): diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c index 9062ba01c..4bfc2c191 100644 --- a/grub-core/loader/multiboot.c +++ b/grub-core/loader/multiboot.c @@ -22,6 +22,8 @@ * need to be implemented: * - drives table * - ROM configuration table + * - SMBIOS tables + * - Networking information */ #include diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c index 799985a1c..f7a05bcac 100644 --- a/grub-core/loader/multiboot_mbi2.c +++ b/grub-core/loader/multiboot_mbi2.c @@ -32,6 +32,7 @@ #include #include #include +#include #if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_MULTIBOOT) || defined (GRUB_MACHINE_QEMU) #include @@ -142,6 +143,10 @@ grub_multiboot_load (grub_file_t file) case MULTIBOOT_TAG_TYPE_VBE: case MULTIBOOT_TAG_TYPE_ELF_SECTIONS: case MULTIBOOT_TAG_TYPE_APM: + case MULTIBOOT_TAG_TYPE_EFI32: + case MULTIBOOT_TAG_TYPE_EFI64: + case MULTIBOOT_TAG_TYPE_ACPI_OLD: + case MULTIBOOT_TAG_TYPE_ACPI_NEW: break; default: @@ -265,6 +270,22 @@ grub_multiboot_load (grub_file_t file) return err; } +static grub_size_t +acpiv2_size (void) +{ +#if GRUB_MACHINE_HAS_ACPI + struct grub_acpi_rsdp_v20 *p = grub_acpi_get_rsdpv2 (); + + if (!p) + return 0; + + return ALIGN_UP (sizeof (struct multiboot_tag_old_acpi) + + p->length, MULTIBOOT_TAG_ALIGN); +#else + return 0; +#endif +} + static grub_size_t grub_multiboot_get_mbi_size (void) { @@ -283,6 +304,11 @@ grub_multiboot_get_mbi_size (void) + grub_get_multiboot_mmap_count () * sizeof (struct multiboot_mmap_entry)), MULTIBOOT_TAG_ALIGN) + ALIGN_UP (sizeof (struct multiboot_tag_framebuffer), MULTIBOOT_TAG_ALIGN) + + ALIGN_UP (sizeof (struct multiboot_tag_efi32), MULTIBOOT_TAG_ALIGN) + + ALIGN_UP (sizeof (struct multiboot_tag_efi64), MULTIBOOT_TAG_ALIGN) + + ALIGN_UP (sizeof (struct multiboot_tag_old_acpi) + + sizeof (struct grub_acpi_rsdp_v10), MULTIBOOT_TAG_ALIGN) + + acpiv2_size () + sizeof (struct multiboot_tag_vbe) + MULTIBOOT_TAG_ALIGN - 1 + sizeof (struct multiboot_tag_apm) + MULTIBOOT_TAG_ALIGN - 1; } @@ -674,7 +700,55 @@ grub_multiboot_make_mbi (grub_uint32_t *target) grub_errno = GRUB_ERR_NONE; } } - + +#if defined (GRUB_MACHINE_EFI) && __x86_64__ + { + struct multiboot_tag_efi64 *tag = (struct multiboot_tag_efi64 *) ptrorig; + tag->type = MULTIBOOT_TAG_TYPE_EFI64; + tag->size = sizeof (*tag); + tag->pointer = (grub_addr_t) grub_efi_system_table; + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + } +#endif + +#if defined (GRUB_MACHINE_EFI) && __i386_ + { + struct multiboot_tag_efi64 *tag = (struct multiboot_tag_efi32 *) ptrorig; + tag->type = MULTIBOOT_TAG_TYPE_EFI32; + tag->size = sizeof (*tag); + tag->pointer = (grub_addr_t) grub_efi_system_table; + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + } +#endif + +#if GRUB_MACHINE_HAS_ACPI + { + struct multiboot_tag_old_acpi *tag = (struct multiboot_tag_old_acpi *) + ptrorig; + struct grub_acpi_rsdp_v10 *a = grub_acpi_get_rsdpv1 (); + if (a) + { + tag->type = MULTIBOOT_TAG_TYPE_ACPI_OLD; + tag->size = sizeof (*tag) + sizeof (*a); + grub_memcpy (tag->rsdp, a, sizeof (*a)); + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + } + } + + { + struct multiboot_tag_new_acpi *tag = (struct multiboot_tag_new_acpi *) + ptrorig; + struct grub_acpi_rsdp_v20 *a = grub_acpi_get_rsdpv2 (); + if (a) + { + tag->type = MULTIBOOT_TAG_TYPE_ACPI_NEW; + tag->size = sizeof (*tag) + a->length; + grub_memcpy (tag->rsdp, a, a->length); + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + } + } +#endif + { struct multiboot_tag *tag = (struct multiboot_tag *) ptrorig; tag->type = MULTIBOOT_TAG_TYPE_END; diff --git a/include/grub/multiboot.h b/include/grub/multiboot.h index 92837d7d2..364dc3ca6 100644 --- a/include/grub/multiboot.h +++ b/include/grub/multiboot.h @@ -62,6 +62,12 @@ grub_err_t grub_multiboot_set_video_mode (void); #define GRUB_MACHINE_HAS_VBE 0 #endif +#if defined (GRUB_MACHINE_EFI) || defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_MULTIBOOT) +#define GRUB_MACHINE_HAS_ACPI 1 +#else +#define GRUB_MACHINE_HAS_ACPI 0 +#endif + #define GRUB_MULTIBOOT_CONSOLE_EGA_TEXT 1 #define GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER 2