From 8eb567e6629c892428c1a563afb6aa40d1a74f64 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 7 Mar 2010 14:59:15 +0100 Subject: [PATCH] Update with newest mbtag spec --- include/grub/multiboot.h | 2 +- include/multiboot2.h | 33 ++++++++++++++- loader/i386/multiboot.c | 4 +- loader/i386/multiboot_mbi.c | 6 ++- loader/i386/multiboot_mbi2.c | 78 +++++++++++++++++++----------------- 5 files changed, 81 insertions(+), 42 deletions(-) diff --git a/include/grub/multiboot.h b/include/grub/multiboot.h index 27d4d816d..c108e5eef 100644 --- a/include/grub/multiboot.h +++ b/include/grub/multiboot.h @@ -44,7 +44,7 @@ grub_err_t grub_multiboot_add_module (grub_addr_t start, grub_size_t size, int argc, char *argv[]); void grub_multiboot_set_bootdev (void); -grub_uint32_t grub_get_multiboot_mmap_len (void); +grub_uint32_t grub_get_multiboot_mmap_count (void); grub_err_t grub_multiboot_set_video_mode (void); #if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU) diff --git a/include/multiboot2.h b/include/multiboot2.h index 20c5c5696..36710ddf6 100644 --- a/include/multiboot2.h +++ b/include/multiboot2.h @@ -51,6 +51,7 @@ /* This flag indicates the use of the address fields in the header. */ #define MULTIBOOT_AOUT_KLUDGE 0x00010000 +#define MULTIBOOT_TAG_ALIGN 8 #define MULTIBOOT_TAG_TYPE_END 0 #define MULTIBOOT_TAG_TYPE_CMDLINE 1 #define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2 @@ -102,7 +103,6 @@ struct multiboot_color struct multiboot_mmap_entry { - multiboot_uint32_t size; multiboot_uint64_t addr; multiboot_uint64_t len; #define MULTIBOOT_MEMORY_AVAILABLE 1 @@ -110,6 +110,7 @@ struct multiboot_mmap_entry #define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3 #define MULTIBOOT_MEMORY_NVS 4 multiboot_uint32_t type; + multiboot_uint32_t zero; } __attribute__((packed)); typedef struct multiboot_mmap_entry multiboot_memory_map_t; @@ -123,6 +124,8 @@ struct multiboot_tag_string { multiboot_uint32_t type; multiboot_uint32_t size; + multiboot_uint32_t entry_size; + multiboot_uint32_t entry_version; char string[0]; }; @@ -156,6 +159,8 @@ struct multiboot_tag_mmap { multiboot_uint32_t type; multiboot_uint32_t size; + multiboot_uint32_t entry_size; + multiboot_uint32_t entry_version; struct multiboot_mmap_entry entries[0]; }; @@ -197,6 +202,7 @@ struct multiboot_tag_framebuffer_common #define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1 #define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2 multiboot_uint8_t framebuffer_type; + multiboot_uint16_t reserved; }; struct multiboot_tag_framebuffer @@ -222,6 +228,31 @@ struct multiboot_tag_framebuffer }; }; +struct multiboot_tag_elf_sections +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint32_t num; + multiboot_uint32_t entsize; + multiboot_uint32_t shndx; + char sections[0]; +}; + +struct multiboot_tag_apm +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint16_t version; + multiboot_uint16_t cseg; + multiboot_uint32_t offset; + multiboot_uint16_t cseg_16; + multiboot_uint16_t dseg; + multiboot_uint16_t flags; + multiboot_uint16_t cseg_len; + multiboot_uint16_t cseg_16_len; + multiboot_uint16_t dseg_len; +}; + #endif /* ! ASM_FILE */ #endif /* ! MULTIBOOT_HEADER */ diff --git a/loader/i386/multiboot.c b/loader/i386/multiboot.c index 5f9751f33..dab81dc8c 100644 --- a/loader/i386/multiboot.c +++ b/loader/i386/multiboot.c @@ -68,7 +68,7 @@ static int accepts_video; /* Return the length of the Multiboot mmap that will be needed to allocate our platform's map. */ grub_uint32_t -grub_get_multiboot_mmap_len (void) +grub_get_multiboot_mmap_count (void) { grub_size_t count = 0; @@ -83,7 +83,7 @@ grub_get_multiboot_mmap_len (void) grub_mmap_iterate (hook); - return count * sizeof (struct multiboot_mmap_entry); + return count; } grub_err_t diff --git a/loader/i386/multiboot_mbi.c b/loader/i386/multiboot_mbi.c index a8133a705..0d5db3c13 100644 --- a/loader/i386/multiboot_mbi.c +++ b/loader/i386/multiboot_mbi.c @@ -53,7 +53,8 @@ grub_multiboot_get_mbi_size (void) { return sizeof (struct multiboot_info) + ALIGN_UP (cmdline_size, 4) + modcnt * sizeof (struct multiboot_mod_list) + total_modcmd - + ALIGN_UP (sizeof(PACKAGE_STRING), 4) + grub_get_multiboot_mmap_len () + + ALIGN_UP (sizeof(PACKAGE_STRING), 4) + + grub_get_multiboot_mmap_count () * sizeof (struct multiboot_mmap_entry) #if GRUB_MACHINE_HAS_VBE + sizeof (struct grub_vbe_info_block) + sizeof (struct grub_vbe_mode_info_block) @@ -233,7 +234,8 @@ grub_multiboot_make_mbi (void *orig, grub_uint32_t dest, grub_off_t buf_off, mbi->mods_count = 0; } - mmap_size = grub_get_multiboot_mmap_len (); + mmap_size = grub_get_multiboot_mmap_count () + * sizeof (struct multiboot_mmap_entry); grub_fill_multiboot_mmap ((struct multiboot_mmap_entry *) ptrorig); mbi->mmap_length = mmap_size; mbi->mmap_addr = ptrdest; diff --git a/loader/i386/multiboot_mbi2.c b/loader/i386/multiboot_mbi2.c index a53bbe50a..ab803734f 100644 --- a/loader/i386/multiboot_mbi2.c +++ b/loader/i386/multiboot_mbi2.c @@ -62,15 +62,17 @@ static grub_uint32_t biosdev, slice, part; grub_size_t grub_multiboot_get_mbi_size (void) { - return sizeof (grub_uint32_t) + sizeof (struct multiboot_tag) - + (sizeof (struct multiboot_tag_string) + ALIGN_UP (cmdline_size, 4)) + return 2 * sizeof (grub_uint32_t) + sizeof (struct multiboot_tag) + (sizeof (struct multiboot_tag_string) - + ALIGN_UP (sizeof (PACKAGE_STRING), 4)) + + ALIGN_UP (cmdline_size, MULTIBOOT_TAG_ALIGN)) + + (sizeof (struct multiboot_tag_string) + + ALIGN_UP (sizeof (PACKAGE_STRING), MULTIBOOT_TAG_ALIGN)) + (modcnt * sizeof (struct multiboot_tag_module) + total_modcmd) + sizeof (struct multiboot_tag_basic_meminfo) - + sizeof (struct multiboot_tag_bootdev) - + (sizeof (struct multiboot_tag_mmap) + grub_get_multiboot_mmap_len ()) - + sizeof (struct multiboot_tag_vbe); + + ALIGN_UP (sizeof (struct multiboot_tag_bootdev), MULTIBOOT_TAG_ALIGN) + + (sizeof (struct multiboot_tag_mmap) + grub_get_multiboot_mmap_count () + * sizeof (struct multiboot_mmap_entry)) + + sizeof (struct multiboot_tag_vbe) + MULTIBOOT_TAG_ALIGN - 1; } #ifdef GRUB_MACHINE_HAS_VBE @@ -98,7 +100,7 @@ fill_vbe_info (struct grub_vbe_mode_info_block **vbe_mode_info_out, *vbe_mode_info_out = (struct grub_vbe_mode_info_block *) &(tag->vbe_mode_info); tag->size = sizeof (struct multiboot_tag_vbe); - *ptrorig += tag->size; + *ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); return GRUB_ERR_NONE; } @@ -106,9 +108,9 @@ fill_vbe_info (struct grub_vbe_mode_info_block **vbe_mode_info_out, /* Fill previously allocated Multiboot mmap. */ static void -grub_fill_multiboot_mmap (struct multiboot_mmap_entry *first_entry) +grub_fill_multiboot_mmap (struct multiboot_tag_mmap *tag) { - struct multiboot_mmap_entry *mmap_entry = (struct multiboot_mmap_entry *) first_entry; + struct multiboot_mmap_entry *mmap_entry = tag->entries; auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type) @@ -137,12 +139,17 @@ grub_fill_multiboot_mmap (struct multiboot_mmap_entry *first_entry) mmap_entry->type = MULTIBOOT_MEMORY_RESERVED; break; } - mmap_entry->size = sizeof (struct multiboot_mmap_entry) - sizeof (mmap_entry->size); mmap_entry++; return 0; } + tag->type = MULTIBOOT_TAG_TYPE_MMAP; + tag->size = sizeof (struct multiboot_tag_mmap) + + sizeof (struct multiboot_mmap_entry) * grub_get_multiboot_mmap_count (); + tag->entry_size = sizeof (struct multiboot_mmap_entry); + tag->entry_version = 0; + grub_mmap_iterate (hook); } @@ -190,7 +197,8 @@ retrieve_video_parameters (grub_uint8_t **ptrorig) tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT; tag->common.size = sizeof (tag->common); - *ptrorig += tag->common.size; + tag->common.reserved = 0; + *ptrorig += ALIGN_UP (tag->common.size, MULTIBOOT_TAG_ALIGN); } return GRUB_ERR_NONE; } @@ -214,6 +222,8 @@ retrieve_video_parameters (grub_uint8_t **ptrorig) tag->common.framebuffer_height = mode_info.height; tag->common.framebuffer_bpp = mode_info.bpp; + + tag->common.reserved = 0; if (mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) { @@ -231,7 +241,6 @@ retrieve_video_parameters (grub_uint8_t **ptrorig) tag->framebuffer_palette[i].green = palette[i].g; tag->framebuffer_palette[i].blue = palette[i].b; } - *ptrorig += tag->common.size; } else { @@ -246,6 +255,7 @@ retrieve_video_parameters (grub_uint8_t **ptrorig) tag->common.size = sizeof (struct multiboot_tag_framebuffer_common) + 6; } + *ptrorig += ALIGN_UP (tag->common.size, MULTIBOOT_TAG_ALIGN); #if HAS_VBE if (driv_id == GRUB_VIDEO_DRIVER_VBE) @@ -264,30 +274,29 @@ grub_multiboot_make_mbi (void *orig, grub_uint32_t dest, grub_off_t buf_off, grub_size_t bufsize) { grub_uint8_t *ptrorig; - grub_uint8_t *mbistart = (grub_uint8_t *) orig + buf_off; + grub_uint8_t *mbistart = (grub_uint8_t *) orig + buf_off + + (ALIGN_UP (dest + buf_off, MULTIBOOT_TAG_ALIGN) - (dest + buf_off)); grub_err_t err; if (bufsize < grub_multiboot_get_mbi_size ()) return grub_error (GRUB_ERR_OUT_OF_MEMORY, "mbi buffer is too small"); - ptrorig = (grub_uint8_t *) orig + buf_off + sizeof (grub_uint32_t); + ptrorig = mbistart + 2 * sizeof (grub_uint32_t); { struct multiboot_tag_string *tag = (struct multiboot_tag_string *) ptrorig; tag->type = MULTIBOOT_TAG_TYPE_CMDLINE; - tag->size = sizeof (struct multiboot_tag_string) - + ALIGN_UP (cmdline_size, 4); + tag->size = sizeof (struct multiboot_tag_string) + cmdline_size; grub_memcpy (tag->string, cmdline, cmdline_size); - ptrorig += tag->size; + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); } { struct multiboot_tag_string *tag = (struct multiboot_tag_string *) ptrorig; tag->type = MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME; - tag->size = sizeof (struct multiboot_tag_string) - + ALIGN_UP (sizeof (PACKAGE_STRING), 4); + tag->size = sizeof (struct multiboot_tag_string) + sizeof (PACKAGE_STRING); grub_memcpy (tag->string, PACKAGE_STRING, sizeof (PACKAGE_STRING)); - ptrorig += tag->size; + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); } { @@ -299,23 +308,18 @@ grub_multiboot_make_mbi (void *orig, grub_uint32_t dest, grub_off_t buf_off, struct multiboot_tag_module *tag = (struct multiboot_tag_module *) ptrorig; tag->type = MULTIBOOT_TAG_TYPE_MODULE; - tag->size = sizeof (struct multiboot_tag_module) - + ALIGN_UP (sizeof (cur->cmdline_size), 4); - + tag->size = sizeof (struct multiboot_tag_module) + cur->cmdline_size; tag->mod_start = dest + cur->start; tag->mod_end = tag->mod_start + cur->size; grub_memcpy (tag->cmdline, cur->cmdline, cur->cmdline_size); - ptrorig += tag->size; + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); } } { struct multiboot_tag_mmap *tag = (struct multiboot_tag_mmap *) ptrorig; - tag->type = MULTIBOOT_TAG_TYPE_MMAP; - tag->size = sizeof (struct multiboot_tag_mmap) - + grub_get_multiboot_mmap_len (); - grub_fill_multiboot_mmap (tag->entries); - ptrorig += tag->size; + grub_fill_multiboot_mmap (tag); + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); } { @@ -327,7 +331,7 @@ grub_multiboot_make_mbi (void *orig, grub_uint32_t dest, grub_off_t buf_off, /* Convert from bytes to kilobytes. */ tag->mem_lower = grub_mmap_get_lower () / 1024; tag->mem_upper = grub_mmap_get_upper () / 1024; - ptrorig += tag->size; + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); } if (bootdev_set) @@ -340,7 +344,7 @@ grub_multiboot_make_mbi (void *orig, grub_uint32_t dest, grub_off_t buf_off, tag->biosdev = biosdev; tag->slice = slice; tag->part = part; - ptrorig += tag->size; + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); } { @@ -356,10 +360,11 @@ grub_multiboot_make_mbi (void *orig, grub_uint32_t dest, grub_off_t buf_off, struct multiboot_tag *tag = (struct multiboot_tag *) ptrorig; tag->type = MULTIBOOT_TAG_TYPE_END; tag->size = sizeof (struct multiboot_tag); - ptrorig += tag->size; + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); } - *(grub_uint32_t *) mbistart = ptrorig - mbistart; + ((grub_uint32_t *) mbistart)[0] = ptrorig - mbistart; + ((grub_uint32_t *) mbistart)[1] = 0; return GRUB_ERR_NONE; } @@ -447,7 +452,7 @@ grub_multiboot_add_module (grub_addr_t start, grub_size_t size, return grub_errno; } newmod->cmdline_size = len; - total_modcmd += ALIGN_UP (len, 4); + total_modcmd += ALIGN_UP (len, MULTIBOOT_TAG_ALIGN); for (i = 0; i < argc; i++) { @@ -495,8 +500,8 @@ grub_multiboot_set_bootdev (void) dev = grub_device_open (0); if (dev && dev->disk && dev->disk->partition) { - - p = dev->disk->partition->partmap->get_name (dev->disk->partition); + char *p0; + p = p0 = dev->disk->partition->partmap->get_name (dev->disk->partition); if (p) { if ((p[0] >= '0') && (p[0] <= '9')) @@ -510,6 +515,7 @@ grub_multiboot_set_bootdev (void) if ((p[0] >= 'a') && (p[0] <= 'z')) part = p[0] - 'a'; } + grub_free (p0); } if (dev) grub_device_close (dev);