grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[multiboot2] Tagged mbi


From: Vladimir 'φ-coder/phcoder' Serbinenko
Subject: [multiboot2] Tagged mbi
Date: Sat, 16 Jan 2010 17:50:00 +0100
User-agent: Mozilla-Thunderbird 2.0.0.22 (X11/20091109)

Here is tagged mbi proposal rebased for multiboot2. I defined begining
of tag buffer as starting with total mbi size to make relocation and
memory mapping trivial.
Current problems:
- I haven't migrated the a.out (as oppose to multiboot kludge) symbols,
drives table and ROM configuration table. I'm not familiar with these
fields. What are they used for?
-Memory usage.  Additionally to the space occupied by payload multiboot
specification uses memory for mbi, ELF sections and modules. Moving all
this information around without overwriting may be a difficult task.
Possible alternatives:
  - Put modules and sections in mbi. But then one-chunk mbi may not find
enough available space in the memory
  - Add a map of memory used by multiboot separately from memory map. I
don't think it's worth it since this information is easily available by
    traversing mbi anyway.
  - Add requirements on position of modules. It actually just moves
complexity from payload to bootloader. (for grub I wrote newreloc layer
for such requirements present in different protocols, it's currently in
late alpha, available at people/phcoder/newreloc)
  - Leave it as is and propose some code to do moving mbi around sanely
under non-copyleft license.


-- 
Regards
Vladimir 'φ-coder/phcoder' Serbinenko

=== added file 'ChangeLog.tag'
--- ChangeLog.tag       1970-01-01 00:00:00 +0000
+++ ChangeLog.tag       2010-01-16 15:25:17 +0000
@@ -0,0 +1,40 @@
+2010-01-16  Vladimir Serbinenko  <address@hidden>
+
+       Multiboot2 tag support
+
+       * conf/i386.rmk (multiboot2_mod_SOURCES): Replace
+       loader/i386/multiboot_mbi.c with loader/i386/multiboot_mbi2.c.
+       * include/grub/i386/multiboot.h (grub_multiboot_real_boot): Removed.
+       (grub_multiboot2_real_boot): Likewise.
+       * include/grub/multiboot.h (grub_multiboot_set_accepts_video): Removed.
+       (grub_get_multiboot_mmap_len): New proto.
+       (grub_fill_multiboot_mmap): Likewise.
+       (grub_multiboot_set_video_mode): Likewise.
+       (grub_multiboot_fill_vbe_info_real): Likewise.
+       * include/multiboot2.h: Resynced with specification.
+       * loader/i386/multiboot_mbi.c (DEFAULT_VIDEO_MODE): Moved from here...
+       * loader/i386/multiboot.c (DEFAULT_VIDEO_MODE): ... here.
+       * loader/i386/multiboot_mbi.c (HAS_VGA_TEXT): Moved from here ..
+       * include/grub/multiboot.h (GRUB_MACHINE_HAS_VGA_TEXT): ... here. All
+       users updated.
+       * loader/i386/multiboot_mbi.c (HAS_VBE): Moved from here ..
+       * include/grub/multiboot.h (GRUB_MACHINE_HAS_VBE): ... here. All
+       users updated.
+       * loader/i386/multiboot_mbi.c (accepts_video): Moved from here...
+       * loader/i386/multiboot.c (accepts_video): ... here. All users updated.
+       * loader/i386/multiboot_mbi.c (grub_multiboot_set_accepts_video):
+       Removed.
+       * loader/i386/multiboot_mbi.c (grub_get_multiboot_mmap_len):
+       Moved from here...
+       * loader/i386/multiboot.c (grub_get_multiboot_mmap_len): ... here.
+       * loader/i386/multiboot_mbi.c (grub_fill_multiboot_mmap):
+       Moved from here...
+       * loader/i386/multiboot.c (grub_fill_multiboot_mmap): ... here.
+       * loader/i386/multiboot_mbi.c (set_video_mode): Moved from here...
+       * loader/i386/multiboot.c (grub_multiboot_set_video_mode): ... here.
+       All users updated.
+       * loader/i386/multiboot_mbi.c (fill_vbe_info): Moved generic parts
+       from here...
+       * loader/i386/multiboot.c (grub_multiboot_fill_vbe_info_real): ... here.
+       All users updated.
+       * loader/i386/multiboot_mbi2.c: New file.

=== modified file 'conf/i386.rmk'
--- conf/i386.rmk       2010-01-15 20:11:51 +0000
+++ conf/i386.rmk       2010-01-16 14:47:50 +0000
@@ -36,7 +36,7 @@
 
 pkglib_MODULES += multiboot2.mod
 multiboot2_mod_SOURCES = loader/i386/multiboot.c \
-                        loader/i386/multiboot_mbi.c \
+                        loader/i386/multiboot_mbi2.c \
                          loader/multiboot_loader.c
 multiboot2_mod_CFLAGS = $(COMMON_CFLAGS) -DGRUB_USE_MULTIBOOT2
 multiboot2_mod_LDFLAGS = $(COMMON_LDFLAGS)

=== modified file 'include/grub/i386/multiboot.h'
--- include/grub/i386/multiboot.h       2009-12-13 18:37:44 +0000
+++ include/grub/i386/multiboot.h       2010-01-16 15:13:53 +0000
@@ -19,14 +19,6 @@
 #ifndef GRUB_MULTIBOOT_CPU_HEADER
 #define GRUB_MULTIBOOT_CPU_HEADER      1
 
-/* The asm part of the multiboot loader.  */
-void grub_multiboot_real_boot (grub_addr_t entry,
-                              struct multiboot_info *mbi)
-     __attribute__ ((noreturn));
-void grub_multiboot2_real_boot (grub_addr_t entry,
-                               struct multiboot_info *mbi)
-     __attribute__ ((noreturn));
-
 extern grub_uint32_t grub_multiboot_payload_eip;
 extern char *grub_multiboot_payload_orig;
 extern grub_addr_t grub_multiboot_payload_dest;

=== modified file 'include/grub/multiboot.h'
--- include/grub/multiboot.h    2010-01-15 15:42:06 +0000
+++ include/grub/multiboot.h    2010-01-16 15:14:18 +0000
@@ -35,8 +35,6 @@
 void grub_multiboot (int argc, char *argv[]);
 void grub_module (int argc, char *argv[]);
 
-void grub_multiboot_set_accepts_video (int val);
-
 grub_size_t grub_multiboot_get_mbi_size (void);
 grub_err_t grub_multiboot_make_mbi (void *orig, grub_uint32_t dest,
                                    grub_off_t buf_off, grub_size_t bufsize);
@@ -46,5 +44,24 @@
                                      int argc, char *argv[]);
 void grub_multiboot_set_bootdev (void);
 
+grub_uint32_t grub_get_multiboot_mmap_len (void);
+void grub_fill_multiboot_mmap (struct multiboot_mmap_entry *first_entry);
+grub_err_t grub_multiboot_set_video_mode (void);
+
+#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || 
defined (GRUB_MACHINE_QEMU)
+#include <grub/i386/pc/vbe.h>
+grub_err_t
+grub_multiboot_fill_vbe_info_real (struct grub_vbe_info_block 
*vbe_control_info,
+                                  struct grub_vbe_mode_info_block 
*vbe_mode_info,
+                                  multiboot_uint16_t *vbe_mode,
+                                  multiboot_uint16_t *vbe_interface_seg,
+                                  multiboot_uint16_t *vbe_interface_off,
+                                  multiboot_uint16_t *vbe_interface_len);
+#define GRUB_MACHINE_HAS_VBE 1
+#define GRUB_MACHINE_HAS_VGA_TEXT 1
+#else
+#define GRUB_MACHINE_HAS_VBE 0
+#define GRUB_MACHINE_HAS_VGA_TEXT 0
+#endif
 
 #endif /* ! GRUB_MULTIBOOT_HEADER */

=== modified file 'include/multiboot2.h'
--- include/multiboot2.h        2010-01-15 15:42:06 +0000
+++ include/multiboot2.h        2010-01-16 15:00:55 +0000
@@ -51,42 +51,15 @@
 /* This flag indicates the use of the address fields in the header.  */
 #define MULTIBOOT_AOUT_KLUDGE                  0x00010000
 
-/* Flags to be set in the 'flags' member of the multiboot info structure.  */
-
-/* is there basic lower/upper memory information? */
-#define MULTIBOOT_INFO_MEMORY                  0x00000001
-/* is there a boot device set? */
-#define MULTIBOOT_INFO_BOOTDEV                 0x00000002
-/* is the command-line defined? */
-#define MULTIBOOT_INFO_CMDLINE                 0x00000004
-/* are there modules to do something with? */
-#define MULTIBOOT_INFO_MODS                    0x00000008
-
-/* These next two are mutually exclusive */
-
-/* is there a symbol table loaded? */
-#define MULTIBOOT_INFO_AOUT_SYMS               0x00000010
-/* is there an ELF section header table? */
-#define MULTIBOOT_INFO_ELF_SHDR                        0X00000020
-
-/* is there a full memory map? */
-#define MULTIBOOT_INFO_MEM_MAP                 0x00000040
-
-/* Is there drive info?  */
-#define MULTIBOOT_INFO_DRIVE_INFO              0x00000080
-
-/* Is there a config table?  */
-#define MULTIBOOT_INFO_CONFIG_TABLE            0x00000100
-
-/* Is there a boot loader name?  */
-#define MULTIBOOT_INFO_BOOT_LOADER_NAME                0x00000200
-
-/* Is there a APM table?  */
-#define MULTIBOOT_INFO_APM_TABLE               0x00000400
-
-/* Is there video information?  */
-#define MULTIBOOT_INFO_VBE_INFO                        0x00000800
-#define MULTIBOOT_INFO_FRAMEBUFFER_INFO                0x00001000
+#define MULTIBOOT_TAG_TYPE_END               0
+#define MULTIBOOT_TAG_TYPE_CMDLINE           1
+#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME  2
+#define MULTIBOOT_TAG_TYPE_MODULE            3
+#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO     4
+#define MULTIBOOT_TAG_TYPE_BOOTDEV           5
+#define MULTIBOOT_TAG_TYPE_MMAP              6
+#define MULTIBOOT_TAG_TYPE_VBE               7
+#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER       8
 
 #ifndef ASM_FILE
 
@@ -120,76 +93,99 @@
   multiboot_uint32_t depth;
 };
 
-/* The symbol table for a.out.  */
-struct multiboot_aout_symbol_table
-{
-  multiboot_uint32_t tabsize;
-  multiboot_uint32_t strsize;
-  multiboot_uint32_t addr;
-  multiboot_uint32_t reserved;
-};
-typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t;
-
-/* The section header table for ELF.  */
-struct multiboot_elf_section_header_table
-{
-  multiboot_uint32_t num;
-  multiboot_uint32_t size;
-  multiboot_uint32_t addr;
-  multiboot_uint32_t shndx;
-};
-typedef struct multiboot_elf_section_header_table 
multiboot_elf_section_header_table_t;
-
-struct multiboot_info
-{
-  /* Multiboot info version number */
-  multiboot_uint32_t flags;
-
-  /* Available memory from BIOS */
+struct multiboot_color
+{
+  multiboot_uint8_t red;
+  multiboot_uint8_t green;
+  multiboot_uint8_t blue;
+};
+
+struct multiboot_mmap_entry
+{
+  multiboot_uint32_t size;
+  multiboot_uint64_t addr;
+  multiboot_uint64_t len;
+#define MULTIBOOT_MEMORY_AVAILABLE             1
+#define MULTIBOOT_MEMORY_RESERVED              2
+  multiboot_uint32_t type;
+} __attribute__((packed));
+typedef struct multiboot_mmap_entry multiboot_memory_map_t;
+
+struct multiboot_tag
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+};
+
+struct multiboot_tag_string
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  char string[0];
+};
+
+struct multiboot_tag_module
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint32_t mod_start;
+  multiboot_uint32_t mod_end;
+  char cmdline[0];
+};
+
+struct multiboot_tag_basic_meminfo
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
   multiboot_uint32_t mem_lower;
   multiboot_uint32_t mem_upper;
-
-  /* "root" partition */
-  multiboot_uint32_t boot_device;
-
-  /* Kernel command line */
-  multiboot_uint32_t cmdline;
-
-  /* Boot-Module list */
-  multiboot_uint32_t mods_count;
-  multiboot_uint32_t mods_addr;
-
-  union
-  {
-    multiboot_aout_symbol_table_t aout_sym;
-    multiboot_elf_section_header_table_t elf_sec;
-  } u;
-
-  /* Memory Mapping buffer */
-  multiboot_uint32_t mmap_length;
-  multiboot_uint32_t mmap_addr;
-
-  /* Drive Info buffer */
-  multiboot_uint32_t drives_length;
-  multiboot_uint32_t drives_addr;
-
-  /* ROM configuration table */
-  multiboot_uint32_t config_table;
-
-  /* Boot Loader Name */
-  multiboot_uint32_t boot_loader_name;
-
-  /* APM table */
-  multiboot_uint32_t apm_table;
-
-  /* Video */
-  multiboot_uint32_t vbe_control_info;
-  multiboot_uint32_t vbe_mode_info;
+};
+
+struct multiboot_tag_bootdev
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint32_t biosdev;
+  multiboot_uint32_t slice;
+  multiboot_uint32_t part;
+};
+
+struct multiboot_tag_mmap
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  struct multiboot_mmap_entry entries[0];  
+};
+
+struct multiboot_vbe_info_block
+{
+  multiboot_uint8_t external_specification[512];
+};
+
+struct multiboot_vbe_mode_info_block
+{
+  multiboot_uint8_t external_specification[256];
+};
+
+struct multiboot_tag_vbe
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+
   multiboot_uint16_t vbe_mode;
   multiboot_uint16_t vbe_interface_seg;
   multiboot_uint16_t vbe_interface_off;
   multiboot_uint16_t vbe_interface_len;
 
+  struct multiboot_vbe_info_block vbe_control_info;
+  struct multiboot_vbe_mode_info_block vbe_mode_info;
+};
+
+struct multiboot_tag_framebuffer_common
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+
   multiboot_uint64_t framebuffer_addr;
   multiboot_uint32_t framebuffer_pitch;
   multiboot_uint32_t framebuffer_width;
@@ -199,12 +195,18 @@
 #define MULTIBOOT_FRAMEBUFFER_TYPE_RGB     1
 #define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT    2
   multiboot_uint8_t framebuffer_type;
+};
+
+struct multiboot_tag_framebuffer
+{
+  struct multiboot_tag_framebuffer_common common;
+
   union
   {
     struct
     {
-      multiboot_uint32_t framebuffer_palette_addr;
       multiboot_uint16_t framebuffer_palette_num_colors;
+      struct multiboot_color framebuffer_palette[0];
     };
     struct
     {
@@ -217,39 +219,6 @@
     };
   };
 };
-typedef struct multiboot_info multiboot_info_t;
-
-struct multiboot_color
-{
-  multiboot_uint8_t red;
-  multiboot_uint8_t green;
-  multiboot_uint8_t blue;
-};
-
-struct multiboot_mmap_entry
-{
-  multiboot_uint32_t size;
-  multiboot_uint64_t addr;
-  multiboot_uint64_t len;
-#define MULTIBOOT_MEMORY_AVAILABLE             1
-#define MULTIBOOT_MEMORY_RESERVED              2
-  multiboot_uint32_t type;
-} __attribute__((packed));
-typedef struct multiboot_mmap_entry multiboot_memory_map_t;
-
-struct multiboot_mod_list
-{
-  /* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */
-  multiboot_uint32_t mod_start;
-  multiboot_uint32_t mod_end;
-
-  /* Module command line */
-  multiboot_uint32_t cmdline;
-
-  /* padding to take it to 16 bytes (must be zero) */
-  multiboot_uint32_t pad;
-};
-typedef struct multiboot_mod_list multiboot_module_t;
 
 #endif /* ! ASM_FILE */
 

=== modified file 'loader/i386/multiboot.c'
--- loader/i386/multiboot.c     2010-01-16 13:00:44 +0000
+++ loader/i386/multiboot.c     2010-01-16 14:47:50 +0000
@@ -44,11 +44,18 @@
 #include <grub/env.h>
 #include <grub/i386/relocator.h>
 #include <grub/video.h>
+#include <grub/memory.h>
 
 #ifdef GRUB_MACHINE_EFI
 #include <grub/efi/efi.h>
 #endif
 
+#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || 
defined (GRUB_MACHINE_QEMU)
+#define DEFAULT_VIDEO_MODE "text"
+#else
+#define DEFAULT_VIDEO_MODE "auto"
+#endif
+
 extern grub_dl_t my_mod;
 static grub_size_t code_size, alloc_mbi;
 
@@ -56,6 +63,135 @@
 grub_addr_t grub_multiboot_payload_dest;
 grub_size_t grub_multiboot_pure_size;
 grub_uint32_t grub_multiboot_payload_eip;
+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_size_t count = 0;
+
+  auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
+  int NESTED_FUNC_ATTR hook (grub_uint64_t addr __attribute__ ((unused)),
+                            grub_uint64_t size __attribute__ ((unused)),
+                            grub_uint32_t type __attribute__ ((unused)))
+    {
+      count++;
+      return 0;
+    }
+
+  grub_mmap_iterate (hook);
+
+  return count * sizeof (struct multiboot_mmap_entry);
+}
+
+/* Fill previously allocated Multiboot mmap.  */
+void
+grub_fill_multiboot_mmap (struct multiboot_mmap_entry *first_entry)
+{
+  struct multiboot_mmap_entry *mmap_entry = (struct multiboot_mmap_entry *) 
first_entry;
+
+  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)
+    {
+      mmap_entry->addr = addr;
+      mmap_entry->len = size;
+      switch (type)
+       {
+       case GRUB_MACHINE_MEMORY_AVAILABLE:
+         mmap_entry->type = MULTIBOOT_MEMORY_AVAILABLE;
+         break;
+         
+       default:
+         mmap_entry->type = MULTIBOOT_MEMORY_RESERVED;
+         break;
+       }
+      mmap_entry->size = sizeof (struct multiboot_mmap_entry) - sizeof 
(mmap_entry->size);
+      mmap_entry++;
+
+      return 0;
+    }
+
+  grub_mmap_iterate (hook);
+}
+
+grub_err_t
+grub_multiboot_set_video_mode (void)
+{
+  grub_err_t err;
+  const char *modevar;
+
+  if (accepts_video || !GRUB_MACHINE_HAS_VGA_TEXT)
+    {
+      modevar = grub_env_get ("gfxpayload");
+      if (! modevar || *modevar == 0)
+       err = grub_video_set_mode (DEFAULT_VIDEO_MODE, 0);
+      else
+       {
+         char *tmp;
+         tmp = grub_malloc (grub_strlen (modevar)
+                            + sizeof (DEFAULT_VIDEO_MODE) + 1);
+         if (! tmp)
+           return grub_errno;
+         grub_sprintf (tmp, "%s;" DEFAULT_VIDEO_MODE, modevar);
+         err = grub_video_set_mode (tmp, 0);
+         grub_free (tmp);
+       }
+    }
+  else
+    err = grub_video_set_mode ("text", 0);
+
+  return err;
+}
+
+#if GRUB_MACHINE_HAS_VBE
+grub_err_t
+grub_multiboot_fill_vbe_info_real (struct grub_vbe_info_block 
*vbe_control_info,
+                                  struct grub_vbe_mode_info_block 
*vbe_mode_info,
+                                  multiboot_uint16_t *vbe_mode,
+                                  multiboot_uint16_t *vbe_interface_seg,
+                                  multiboot_uint16_t *vbe_interface_off,
+                                  multiboot_uint16_t *vbe_interface_len)
+{
+  grub_vbe_status_t status;
+  void *scratch = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
+    
+  status = grub_vbe_bios_get_controller_info (scratch);
+  if (status != GRUB_VBE_STATUS_OK)
+    return grub_error (GRUB_ERR_IO, "Can't get controller info.");  
+  grub_memcpy (vbe_control_info, scratch, sizeof (struct grub_vbe_info_block));
+  
+  status = grub_vbe_bios_get_mode (scratch);
+  *vbe_mode = *(grub_uint32_t *) scratch;
+  if (status != GRUB_VBE_STATUS_OK)
+    return grub_error (GRUB_ERR_IO, "can't get VBE mode");
+
+  /* get_mode_info isn't available for mode 3.  */
+  if (*vbe_mode == 3)
+    {
+      grub_memset (vbe_mode_info, 0, sizeof (struct grub_vbe_mode_info_block));
+      vbe_mode_info->memory_model = GRUB_VBE_MEMORY_MODEL_TEXT;
+      vbe_mode_info->x_resolution = 80;
+      vbe_mode_info->y_resolution = 25;
+    }
+  else
+    {
+      status = grub_vbe_bios_get_mode_info (*vbe_mode, scratch);
+      if (status != GRUB_VBE_STATUS_OK)
+       return grub_error (GRUB_ERR_IO, "can't get mode info");
+      grub_memcpy (vbe_mode_info, scratch,
+                  sizeof (struct grub_vbe_mode_info_block));
+    }
+      
+  /* FIXME: retrieve those.  */
+  *vbe_interface_seg = 0;
+  *vbe_interface_off = 0;
+  *vbe_interface_len = 0;
+  
+  return GRUB_ERR_NONE;
+}
+#endif
 
 static grub_err_t
 grub_multiboot_boot (void)
@@ -265,7 +401,7 @@
        }
     }
 
-  grub_multiboot_set_accepts_video (!!(header->flags & MULTIBOOT_VIDEO_MODE));
+  accepts_video = !!(header->flags & MULTIBOOT_VIDEO_MODE);
 
   grub_multiboot_set_bootdev ();
 

=== modified file 'loader/i386/multiboot_mbi.c'
--- loader/i386/multiboot_mbi.c 2010-01-15 15:42:06 +0000
+++ loader/i386/multiboot_mbi.c 2010-01-16 15:30:53 +0000
@@ -31,17 +31,6 @@
 #include <grub/env.h>
 #include <grub/video.h>
 
-#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || 
defined (GRUB_MACHINE_QEMU)
-#include <grub/i386/pc/vbe.h>
-#define DEFAULT_VIDEO_MODE "text"
-#define HAS_VGA_TEXT 1
-#define HAS_VBE 1
-#else
-#define DEFAULT_VIDEO_MODE "auto"
-#define HAS_VGA_TEXT 0
-#define HAS_VBE 0
-#endif
-
 struct module
 {
   struct module *next;
@@ -58,34 +47,6 @@
 static char *cmdline = NULL;
 static grub_uint32_t bootdev;
 static int bootdev_set;
-static int accepts_video;
-
-void
-grub_multiboot_set_accepts_video (int val)
-{
-  accepts_video = val;
-}
-
-/* Return the length of the Multiboot mmap that will be needed to allocate
-   our platform's map.  */
-static grub_uint32_t
-grub_get_multiboot_mmap_len (void)
-{
-  grub_size_t count = 0;
-
-  auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
-  int NESTED_FUNC_ATTR hook (grub_uint64_t addr __attribute__ ((unused)),
-                            grub_uint64_t size __attribute__ ((unused)),
-                            grub_uint32_t type __attribute__ ((unused)))
-    {
-      count++;
-      return 0;
-    }
-
-  grub_mmap_iterate (hook);
-
-  return count * sizeof (struct multiboot_mmap_entry);
-}
 
 grub_size_t
 grub_multiboot_get_mbi_size (void)
@@ -93,142 +54,45 @@
   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 ()
-#if HAS_VBE
+#if GRUB_MACHINE_HAS_VBE
     + sizeof (struct grub_vbe_info_block)
     + sizeof (struct grub_vbe_mode_info_block)
 #endif
     + 256 * sizeof (struct multiboot_color);
 }
 
-/* Fill previously allocated Multiboot mmap.  */
-static void
-grub_fill_multiboot_mmap (struct multiboot_mmap_entry *first_entry)
-{
-  struct multiboot_mmap_entry *mmap_entry = (struct multiboot_mmap_entry *) 
first_entry;
-
-  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)
-    {
-      mmap_entry->addr = addr;
-      mmap_entry->len = size;
-      switch (type)
-       {
-       case GRUB_MACHINE_MEMORY_AVAILABLE:
-         mmap_entry->type = MULTIBOOT_MEMORY_AVAILABLE;
-         break;
-         
-       default:
-         mmap_entry->type = MULTIBOOT_MEMORY_RESERVED;
-         break;
-       }
-      mmap_entry->size = sizeof (struct multiboot_mmap_entry) - sizeof 
(mmap_entry->size);
-      mmap_entry++;
-
-      return 0;
-    }
-
-  grub_mmap_iterate (hook);
-}
-
+#if GRUB_MACHINE_HAS_VBE
 static grub_err_t
-set_video_mode (void)
+fill_vbe_info (struct multiboot_info *mbi,
+              struct grub_vbe_mode_info_block **vbe_mode_info_out,
+              grub_uint8_t *ptrorig, grub_addr_t ptrdest)
 {
+  struct grub_vbe_info_block *vbe_control_info;
+  struct grub_vbe_mode_info_block *vbe_mode_info;
   grub_err_t err;
-  const char *modevar;
-
-  if (accepts_video || !HAS_VGA_TEXT)
-    {
-      modevar = grub_env_get ("gfxpayload");
-      if (! modevar || *modevar == 0)
-       err = grub_video_set_mode (DEFAULT_VIDEO_MODE, 0);
-      else
-       {
-         char *tmp;
-         tmp = grub_malloc (grub_strlen (modevar)
-                            + sizeof (DEFAULT_VIDEO_MODE) + 1);
-         if (! tmp)
-           return grub_errno;
-         grub_sprintf (tmp, "%s;" DEFAULT_VIDEO_MODE, modevar);
-         err = grub_video_set_mode (tmp, 0);
-         grub_free (tmp);
-       }
-    }
-  else
-    err = grub_video_set_mode ("text", 0);
-
-  return err;
-}
-
-#if HAS_VBE
-static grub_err_t
-fill_vbe_info (struct multiboot_info *mbi, grub_uint8_t *ptrorig,
-              grub_uint32_t ptrdest, int fill_generic)
-{
-  grub_vbe_status_t status;
-  grub_uint32_t vbe_mode;
-  void *scratch = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
-  struct grub_vbe_mode_info_block *mode_info;
-    
-  status = grub_vbe_bios_get_controller_info (scratch);
-  if (status != GRUB_VBE_STATUS_OK)
-    return grub_error (GRUB_ERR_IO, "Can't get controller info.");
-  
+
+  vbe_control_info = (struct grub_vbe_info_block *) ptrorig;
   mbi->vbe_control_info = ptrdest;
-  grub_memcpy (ptrorig, scratch, sizeof (struct grub_vbe_info_block));
   ptrorig += sizeof (struct grub_vbe_info_block);
   ptrdest += sizeof (struct grub_vbe_info_block);
-  
-  status = grub_vbe_bios_get_mode (scratch);
-  vbe_mode = *(grub_uint32_t *) scratch;
-  if (status != GRUB_VBE_STATUS_OK)
-    return grub_error (GRUB_ERR_IO, "can't get VBE mode");
-  mbi->vbe_mode = vbe_mode;
-
-  mode_info = (struct grub_vbe_mode_info_block *) ptrorig;
+  vbe_mode_info = (struct grub_vbe_mode_info_block *) ptrorig;
   mbi->vbe_mode_info = ptrdest;
-  /* get_mode_info isn't available for mode 3.  */
-  if (vbe_mode == 3)
-    {
-      grub_memset (mode_info, 0, sizeof (struct grub_vbe_mode_info_block));
-      mode_info->memory_model = GRUB_VBE_MEMORY_MODEL_TEXT;
-      mode_info->x_resolution = 80;
-      mode_info->y_resolution = 25;
-    }
-  else
-    {
-      status = grub_vbe_bios_get_mode_info (vbe_mode, scratch);
-      if (status != GRUB_VBE_STATUS_OK)
-       return grub_error (GRUB_ERR_IO, "can't get mode info");
-      grub_memcpy (mode_info, scratch,
-                  sizeof (struct grub_vbe_mode_info_block));
-    }
   ptrorig += sizeof (struct grub_vbe_mode_info_block);
   ptrdest += sizeof (struct grub_vbe_mode_info_block);
-      
-  /* FIXME: retrieve those.  */
-  mbi->vbe_interface_seg = 0;
-  mbi->vbe_interface_off = 0;
-  mbi->vbe_interface_len = 0;
   
+  err = grub_multiboot_fill_vbe_info_real (vbe_control_info, vbe_mode_info,
+                                          &mbi->vbe_mode,
+                                          &mbi->vbe_interface_seg,
+                                          &mbi->vbe_interface_off,
+                                          &mbi->vbe_interface_len);
+  if (err)
+    return err;
   mbi->flags |= MULTIBOOT_INFO_VBE_INFO;
-
-  if (fill_generic && mode_info->memory_model == GRUB_VBE_MEMORY_MODEL_TEXT)
-    {
-      mbi->framebuffer_addr = 0xb8000;
-
-      mbi->framebuffer_pitch = 2 * mode_info->x_resolution;    
-      mbi->framebuffer_width = mode_info->x_resolution;
-      mbi->framebuffer_height = mode_info->y_resolution;
-
-      mbi->framebuffer_bpp = 16;
-
-      mbi->framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT;
-
-      mbi->flags |= MULTIBOOT_INFO_FRAMEBUFFER_INFO;
-    }
-
+  if (vbe_mode_info_out)
+    *vbe_mode_info_out = vbe_mode_info;
   return GRUB_ERR_NONE;
 }
+
 #endif
 
 static grub_err_t
@@ -241,7 +105,7 @@
   grub_video_driver_id_t driv_id;
   struct grub_video_palette_data palette[256];
 
-  err = set_video_mode ();
+  err = grub_multiboot_set_video_mode ();
   if (err)
     {
       grub_print_error ();
@@ -251,9 +115,29 @@
   grub_video_get_palette (0, ARRAY_SIZE (palette), palette);
 
   driv_id = grub_video_get_driver_id ();
-#if HAS_VGA_TEXT
+#if GRUB_MACHINE_HAS_VGA_TEXT
   if (driv_id == GRUB_VIDEO_DRIVER_NONE)
-    return fill_vbe_info (mbi, ptrorig, ptrdest, 1);
+    {
+      struct grub_vbe_mode_info_block *vbe_mode_info;
+      err = fill_vbe_info (mbi, &vbe_mode_info, ptrorig, ptrdest);
+      if (err)
+       return err;
+      if (vbe_mode_info->memory_model == GRUB_VBE_MEMORY_MODEL_TEXT)
+       {
+         mbi->framebuffer_addr = 0xb8000;
+         
+         mbi->framebuffer_pitch = 2 * vbe_mode_info->x_resolution;     
+         mbi->framebuffer_width = vbe_mode_info->x_resolution;
+         mbi->framebuffer_height = vbe_mode_info->y_resolution;
+
+         mbi->framebuffer_bpp = 16;
+         
+         mbi->framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT;
+
+         mbi->flags |= MULTIBOOT_INFO_FRAMEBUFFER_INFO;
+       }
+      return GRUB_ERR_NONE;
+    }
 #else
   if (driv_id == GRUB_VIDEO_DRIVER_NONE)
     return GRUB_ERR_NONE;
@@ -305,9 +189,13 @@
 
   mbi->flags |= MULTIBOOT_INFO_FRAMEBUFFER_INFO;
 
-#if HAS_VBE
+#if GRUB_MACHINE_HAS_VBE
   if (driv_id == GRUB_VIDEO_DRIVER_VBE)
-    return fill_vbe_info (mbi, ptrorig, ptrdest, 0);
+    {
+      err = fill_vbe_info (mbi, NULL, ptrorig, ptrdest);
+      if (err)
+       return err;
+    }
 #endif
 
   return GRUB_ERR_NONE;
@@ -396,7 +284,7 @@
       grub_print_error ();
       grub_errno = GRUB_ERR_NONE;
     }
-#if HAS_VBE
+#if GRUB_MACHINE_HAS_VBE
   ptrorig += sizeof (struct grub_vbe_info_block);
   ptrdest += sizeof (struct grub_vbe_info_block);
   ptrorig += sizeof (struct grub_vbe_mode_info_block);
@@ -529,6 +417,9 @@
   biosdev = 0xffffffff;
 #endif
 
+  if (biosdev == 0xffffffff)
+    return;
+
   dev = grub_device_open (0);
   if (dev && dev->disk && dev->disk->partition)
     {

=== added file 'loader/i386/multiboot_mbi2.c'
--- loader/i386/multiboot_mbi2.c        1970-01-01 00:00:00 +0000
+++ loader/i386/multiboot_mbi2.c        2010-01-16 15:40:14 +0000
@@ -0,0 +1,476 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008,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/machine/memory.h>
+#include <grub/memory.h>
+#ifdef GRUB_MACHINE_PCBIOS
+#include <grub/machine/biosnum.h>
+#endif
+#include <grub/multiboot.h>
+#include <grub/cpu/multiboot.h>
+#include <grub/disk.h>
+#include <grub/device.h>
+#include <grub/partition.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/env.h>
+#include <grub/video.h>
+
+#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || 
defined (GRUB_MACHINE_QEMU)
+#include <grub/i386/pc/vbe.h>
+#define DEFAULT_VIDEO_MODE "text"
+#define HAS_VGA_TEXT 1
+#define HAS_VBE 1
+#else
+#define DEFAULT_VIDEO_MODE "auto"
+#define HAS_VGA_TEXT 0
+#define HAS_VBE 0
+#endif
+
+struct module
+{
+  struct module *next;
+  grub_addr_t start;
+  grub_size_t size;
+  char *cmdline;
+  int cmdline_size;
+};
+
+struct module *modules, *modules_last;
+static grub_size_t cmdline_size;
+static grub_size_t total_modcmd;
+static unsigned modcnt;
+static char *cmdline = NULL;
+static int bootdev_set;
+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))
+    + (sizeof (struct multiboot_tag_string)
+       + ALIGN_UP (sizeof (PACKAGE_STRING), 4))
+    + (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);
+}
+
+#ifdef GRUB_MACHINE_HAS_VBE
+
+static grub_err_t
+fill_vbe_info (struct grub_vbe_mode_info_block **vbe_mode_info_out,
+              grub_uint8_t **ptrorig)
+{
+  struct multiboot_tag_vbe *tag = (struct multiboot_tag_vbe *) *ptrorig;
+  grub_err_t err;
+
+  tag->type = MULTIBOOT_TAG_TYPE_VBE;
+  tag->size = 0;
+  err = grub_multiboot_fill_vbe_info_real ((struct grub_vbe_info_block *)
+                                          &(tag->vbe_control_info),
+                                          (struct grub_vbe_mode_info_block *) 
+                                          &(tag->vbe_mode_info),
+                                          &(tag->vbe_mode),
+                                          &(tag->vbe_interface_seg),
+                                          &(tag->vbe_interface_off),
+                                          &(tag->vbe_interface_len));
+  if (err)
+    return err;
+  if (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;
+  return GRUB_ERR_NONE;
+}
+
+#endif
+
+static grub_err_t
+retrieve_video_parameters (grub_uint8_t **ptrorig)
+{
+  grub_err_t err;
+  struct grub_video_mode_info mode_info;
+  void *framebuffer;
+  grub_video_driver_id_t driv_id;
+  struct grub_video_palette_data palette[256];
+  struct multiboot_tag_framebuffer *tag
+    = (struct multiboot_tag_framebuffer *) *ptrorig;
+
+  err = grub_multiboot_set_video_mode ();
+  if (err)
+    {
+      grub_print_error ();
+      grub_errno = GRUB_ERR_NONE;
+    }
+
+  grub_video_get_palette (0, ARRAY_SIZE (palette), palette);
+
+  driv_id = grub_video_get_driver_id ();
+#if HAS_VGA_TEXT
+  if (driv_id == GRUB_VIDEO_DRIVER_NONE)
+    {
+      struct grub_vbe_mode_info_block *vbe_mode_info;
+      err = fill_vbe_info (&vbe_mode_info, ptrorig);
+      if (err)
+       return err;
+      if (vbe_mode_info->memory_model == GRUB_VBE_MEMORY_MODEL_TEXT)
+       {
+         tag = (struct multiboot_tag_framebuffer *) *ptrorig;
+         tag->common.type = MULTIBOOT_TAG_TYPE_FRAMEBUFFER;
+         tag->common.size = 0;
+
+         tag->common.framebuffer_addr = 0xb8000;
+         
+         tag->common.framebuffer_pitch = 2 * vbe_mode_info->x_resolution;      
+         tag->common.framebuffer_width = vbe_mode_info->x_resolution;
+         tag->common.framebuffer_height = vbe_mode_info->y_resolution;
+
+         tag->common.framebuffer_bpp = 16;
+         
+         tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT;
+         tag->common.size = sizeof (tag->common);
+         *ptrorig += tag->common.size;
+       }
+      return GRUB_ERR_NONE;
+    }
+#else
+  if (driv_id == GRUB_VIDEO_DRIVER_NONE)
+    return GRUB_ERR_NONE;
+#endif
+
+  err = grub_video_get_info_and_fini (&mode_info, &framebuffer);
+  if (err)
+    return err;
+
+  tag = (struct multiboot_tag_framebuffer *) *ptrorig;
+  tag->common.type = MULTIBOOT_TAG_TYPE_FRAMEBUFFER;
+  tag->common.size = 0;
+
+  tag->common.framebuffer_addr = (grub_addr_t) framebuffer;
+  tag->common.framebuffer_pitch = mode_info.pitch;
+
+  tag->common.framebuffer_width = mode_info.width;
+  tag->common.framebuffer_height = mode_info.height;
+
+  tag->common.framebuffer_bpp = mode_info.bpp;
+      
+  if (mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR)
+    {
+      unsigned i;
+      tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED;
+      tag->framebuffer_palette_num_colors = mode_info.number_of_colors;
+      if (tag->framebuffer_palette_num_colors > ARRAY_SIZE (palette))
+       tag->framebuffer_palette_num_colors = ARRAY_SIZE (palette);
+      tag->common.size = sizeof (struct multiboot_tag_framebuffer_common)
+       + sizeof (multiboot_uint16_t) + tag->framebuffer_palette_num_colors
+       * sizeof (struct multiboot_color);
+      for (i = 0; i < tag->framebuffer_palette_num_colors; i++)
+       {
+         tag->framebuffer_palette[i].red = palette[i].r;
+         tag->framebuffer_palette[i].green = palette[i].g;
+         tag->framebuffer_palette[i].blue = palette[i].b;
+       }
+      *ptrorig += tag->common.size;
+    }
+  else
+    {
+      tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_RGB;
+      tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_RGB;
+      tag->framebuffer_red_field_position = mode_info.green_field_pos;
+      tag->framebuffer_red_mask_size = mode_info.green_mask_size;
+      tag->framebuffer_green_field_position = mode_info.green_field_pos;
+      tag->framebuffer_green_mask_size = mode_info.green_mask_size;
+      tag->framebuffer_blue_field_position = mode_info.blue_field_pos;
+      tag->framebuffer_blue_mask_size = mode_info.blue_mask_size;
+
+      tag->common.size = sizeof (struct multiboot_tag_framebuffer_common) + 6;
+    }
+
+#if HAS_VBE
+  if (driv_id == GRUB_VIDEO_DRIVER_VBE)
+    {
+      err = fill_vbe_info (NULL, ptrorig);
+      if (err)
+       return err;
+    }
+#endif
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+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_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);
+
+  {
+    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); 
+    grub_memcpy (tag->string, cmdline, cmdline_size);
+    ptrorig += tag->size;
+  }
+
+  {
+    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); 
+    grub_memcpy (tag->string, PACKAGE_STRING, sizeof (PACKAGE_STRING));
+    ptrorig += tag->size;
+  }
+
+  {
+    unsigned i;
+    struct module *cur;
+
+    for (i = 0, cur = modules; i < modcnt; i++, cur = cur->next)
+      {
+       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->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;
+      }
+  }
+
+  {
+    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;
+  }
+
+  {
+    struct multiboot_tag_basic_meminfo *tag
+      = (struct multiboot_tag_basic_meminfo *) ptrorig;
+    tag->type = MULTIBOOT_TAG_TYPE_BASIC_MEMINFO;
+    tag->size = sizeof (struct multiboot_tag_basic_meminfo); 
+
+    /* Convert from bytes to kilobytes.  */
+    tag->mem_lower = grub_mmap_get_lower () / 1024;
+    tag->mem_upper = grub_mmap_get_upper () / 1024;
+    ptrorig += tag->size;
+  }
+
+  if (bootdev_set)
+    {
+      struct multiboot_tag_bootdev *tag
+       = (struct multiboot_tag_bootdev *) ptrorig;
+      tag->type = MULTIBOOT_TAG_TYPE_BOOTDEV;
+      tag->size = sizeof (struct multiboot_tag_bootdev); 
+
+      tag->biosdev = biosdev;
+      tag->slice = slice;
+      tag->part = part;
+      ptrorig += tag->size;
+    }
+
+  {
+    err = retrieve_video_parameters (&ptrorig);
+    if (err)
+      {
+       grub_print_error ();
+       grub_errno = GRUB_ERR_NONE;
+      }
+  }
+  
+  {
+    struct multiboot_tag *tag = (struct multiboot_tag *) ptrorig;
+    tag->type = MULTIBOOT_TAG_TYPE_END;
+    tag->size = sizeof (struct multiboot_tag);
+    ptrorig += tag->size;
+  }
+
+  *(grub_uint32_t *) mbistart = ptrorig - mbistart;
+
+  return GRUB_ERR_NONE;
+}
+
+void
+grub_multiboot_free_mbi (void)
+{
+  struct module *cur, *next;
+
+  cmdline_size = 0;
+  total_modcmd = 0;
+  modcnt = 0;
+  grub_free (cmdline);
+  cmdline = NULL;
+  bootdev_set = 0;
+
+  for (cur = modules; cur; cur = next)
+    {
+      next = cur->next;
+      grub_free (cur->cmdline);
+      grub_free (cur);
+    }
+  modules = NULL;
+  modules_last = NULL;
+}
+
+grub_err_t
+grub_multiboot_init_mbi (int argc, char *argv[])
+{
+  grub_ssize_t len = 0;
+  char *p;
+  int i;
+
+  grub_multiboot_free_mbi ();
+
+  for (i = 0; i < argc; i++)
+    len += grub_strlen (argv[i]) + 1;
+  if (len == 0)
+    len = 1;
+
+  cmdline = p = grub_malloc (len);
+  if (! cmdline)
+    return grub_errno;
+  cmdline_size = len;
+
+  for (i = 0; i < argc; i++)
+    {
+      p = grub_stpcpy (p, argv[i]);
+      *(p++) = ' ';
+    }
+
+  /* Remove the space after the last word.  */
+  if (p != cmdline)
+    p--;
+  *p = '\0';
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_multiboot_add_module (grub_addr_t start, grub_size_t size,
+                          int argc, char *argv[])
+{
+  struct module *newmod;
+  char *p;
+  grub_ssize_t len = 0;
+  int i;
+
+  newmod = grub_malloc (sizeof (*newmod));
+  if (!newmod)
+    return grub_errno;
+  newmod->start = start;
+  newmod->size = size;
+
+  for (i = 0; i < argc; i++)
+    len += grub_strlen (argv[i]) + 1;
+
+  if (len == 0)
+    len = 1;
+
+  newmod->cmdline = p = grub_malloc (len);
+  if (! newmod->cmdline)
+    {
+      grub_free (newmod);
+      return grub_errno;
+    }
+  newmod->cmdline_size = len;
+  total_modcmd += ALIGN_UP (len, 4);
+
+  for (i = 0; i < argc; i++)
+    {
+      p = grub_stpcpy (p, argv[i]);
+      *(p++) = ' ';
+    }
+
+  /* Remove the space after the last word.  */
+  if (p != newmod->cmdline)
+    p--;
+  *p = '\0';
+
+  if (modules_last)
+    modules_last->next = newmod;
+  else
+    {
+      modules = newmod;
+      modules_last->next = NULL;
+    }
+  modules_last = newmod;
+
+  modcnt++;
+
+  return GRUB_ERR_NONE;
+}
+
+void
+grub_multiboot_set_bootdev (void)
+{
+  char *p;
+  grub_device_t dev;
+
+  slice = ~0;
+  part = ~0;
+
+#ifdef GRUB_MACHINE_PCBIOS
+  biosdev = grub_get_root_biosnumber ();
+#else
+  biosdev = 0xffffffff;
+#endif
+
+  if (biosdev == 0xffffffff)
+    return;
+
+  dev = grub_device_open (0);
+  if (dev && dev->disk && dev->disk->partition)
+    {
+
+      p = dev->disk->partition->partmap->get_name (dev->disk->partition);
+      if (p)
+       {
+         if ((p[0] >= '0') && (p[0] <= '9'))
+           {
+             slice = grub_strtoul (p, &p, 0) - 1;
+
+             if ((p) && (p[0] == ','))
+               p++;
+           }
+
+         if ((p[0] >= 'a') && (p[0] <= 'z'))
+           part = p[0] - 'a';
+       }
+    }
+  if (dev)
+    grub_device_close (dev);
+
+  bootdev_set = 1;
+}

=== modified file 'doc/kernel.c'
--- doc/kernel.c        2010-01-16 16:27:35 +0000
+++ doc/kernel.c        2010-01-16 16:30:52 +0000
@@ -19,9 +19,6 @@
 
 /* Macros.  */
 
-/* Check if the bit BIT in FLAGS is set.  */
-#define CHECK_FLAG(flags,bit)  ((flags) & (1 << (bit)))
-
 /* Some screen stuff.  */
 /* The number of columns.  */
 #define COLUMNS                        80
@@ -51,9 +48,10 @@
    pointed by ADDR.  */
 void
 cmain (unsigned long magic, unsigned long addr)
-{
-  multiboot_info_t *mbi;
-  
+{  
+  struct multiboot_tag *tag;
+  unsigned size;
+
   /* Clear the screen.  */
   cls ();
 
@@ -64,177 +62,155 @@
       return;
     }
 
-  /* Set MBI to the address of the Multiboot information structure.  */
-  mbi = (multiboot_info_t *) addr;
-
-  /* Print out the flags.  */
-  printf ("flags = 0x%x\n", (unsigned) mbi->flags);
-
-  /* Are mem_* valid?  */
-  if (CHECK_FLAG (mbi->flags, 0))
-    printf ("mem_lower = %uKB, mem_upper = %uKB\n",
-           (unsigned) mbi->mem_lower, (unsigned) mbi->mem_upper);
-
-  /* Is boot_device valid?  */
-  if (CHECK_FLAG (mbi->flags, 1))
-    printf ("boot_device = 0x%x\n", (unsigned) mbi->boot_device);
-  
-  /* Is the command line passed?  */
-  if (CHECK_FLAG (mbi->flags, 2))
-    printf ("cmdline = %s\n", (char *) mbi->cmdline);
-
-  /* Are mods_* valid?  */
-  if (CHECK_FLAG (mbi->flags, 3))
-    {
-      multiboot_module_t *mod;
-      int i;
-      
-      printf ("mods_count = %d, mods_addr = 0x%x\n",
-             (int) mbi->mods_count, (int) mbi->mods_addr);
-      for (i = 0, mod = (multiboot_module_t *) mbi->mods_addr;
-          i < mbi->mods_count;
-          i++, mod++)
-       printf (" mod_start = 0x%x, mod_end = 0x%x, cmdline = %s\n",
-               (unsigned) mod->mod_start,
-               (unsigned) mod->mod_end,
-               (char *) mod->cmdline);
-    }
-
-  /* Bits 4 and 5 are mutually exclusive!  */
-  if (CHECK_FLAG (mbi->flags, 4) && CHECK_FLAG (mbi->flags, 5))
-    {
-      printf ("Both bits 4 and 5 are set.\n");
-      return;
-    }
-
-  /* Is the symbol table of a.out valid?  */
-  if (CHECK_FLAG (mbi->flags, 4))
-    {
-      multiboot_aout_symbol_table_t *multiboot_aout_sym = &(mbi->u.aout_sym);
-      
-      printf ("multiboot_aout_symbol_table: tabsize = 0x%0x, "
-             "strsize = 0x%x, addr = 0x%x\n",
-             (unsigned) multiboot_aout_sym->tabsize,
-             (unsigned) multiboot_aout_sym->strsize,
-             (unsigned) multiboot_aout_sym->addr);
-    }
-
-  /* Is the section header table of ELF valid?  */
-  if (CHECK_FLAG (mbi->flags, 5))
-    {
-      multiboot_elf_section_header_table_t *multiboot_elf_sec = 
&(mbi->u.elf_sec);
-
-      printf ("multiboot_elf_sec: num = %u, size = 0x%x,"
-             " addr = 0x%x, shndx = 0x%x\n",
-             (unsigned) multiboot_elf_sec->num, (unsigned) 
multiboot_elf_sec->size,
-             (unsigned) multiboot_elf_sec->addr, (unsigned) 
multiboot_elf_sec->shndx);
-    }
-
-  /* Are mmap_* valid?  */
-  if (CHECK_FLAG (mbi->flags, 6))
-    {
-      multiboot_memory_map_t *mmap;
-      
-      printf ("mmap_addr = 0x%x, mmap_length = 0x%x\n",
-             (unsigned) mbi->mmap_addr, (unsigned) mbi->mmap_length);
-      for (mmap = (multiboot_memory_map_t *) mbi->mmap_addr;
-          (unsigned long) mmap < mbi->mmap_addr + mbi->mmap_length;
-          mmap = (multiboot_memory_map_t *) ((unsigned long) mmap
-                                   + mmap->size + sizeof (mmap->size)))
-       printf (" size = 0x%x, base_addr = 0x%x%x,"
-               " length = 0x%x%x, type = 0x%x\n",
-               (unsigned) mmap->size,
-               (unsigned) (mmap->addr >> 32),
-               (unsigned) (mmap->addr & 0xffffffff),
-               (unsigned) (mmap->len >> 32),
-               (unsigned) (mmap->len & 0xffffffff),
-               (unsigned) mmap->type);
-    }
-
-  /* Draw diagonal blue line.  */
-  if (CHECK_FLAG (mbi->flags, 12))
-    {
-      multiboot_uint32_t color;
-      unsigned i;
-      void *fb = (void *) (unsigned long) mbi->framebuffer_addr;
-
-      switch (mbi->framebuffer_type)
+  size = *(unsigned *) addr;
+  printf ("Announced mbi size 0x%x\n", size);
+  for (tag = (struct multiboot_tag *) (addr + 4);
+       tag->type != MULTIBOOT_TAG_TYPE_END;
+       tag = (struct multiboot_tag *) ((multiboot_uint8_t *) tag + tag->size))
+    {
+      printf ("Tag 0x%x, Size 0x%x\n", tag->type, tag->size);
+      switch (tag->type)
        {
-       case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED:
-         {
-           unsigned best_distance, distance;
-           struct multiboot_color *palette;
-           
-           palette = (struct multiboot_color *) mbi->framebuffer_palette_addr;
-
-           color = 0;
-           best_distance = 4*256*256;
-           
-           for (i = 0; i < mbi->framebuffer_palette_num_colors; i++)
-             {
-               distance = (0xff - palette[i].blue) * (0xff - palette[i].blue)
-                 + palette[i].red * palette[i].red
-                 + palette[i].green * palette[i].green;
-               if (distance < best_distance)
+       case MULTIBOOT_TAG_TYPE_CMDLINE:
+         printf ("Command line = %s\n",
+                 ((struct multiboot_tag_string *) tag)->string);
+         break;
+       case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME:
+         printf ("Boot loader name = %s\n",
+                 ((struct multiboot_tag_string *) tag)->string);
+         break;
+       case MULTIBOOT_TAG_TYPE_MODULE:
+         printf ("Module at 0x%x-0x%x. Command line %s\n",
+                 ((struct multiboot_tag_module *) tag)->mod_start,
+                 ((struct multiboot_tag_module *) tag)->mod_end,
+                 ((struct multiboot_tag_module *) tag)->cmdline);
+         break;
+       case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO:
+         printf ("mem_lower = %uKB, mem_upper = %uKB\n",
+                 ((struct multiboot_tag_basic_meminfo *) tag)->mem_lower,
+                 ((struct multiboot_tag_basic_meminfo *) tag)->mem_upper);
+         break;
+       case MULTIBOOT_TAG_TYPE_BOOTDEV:
+         printf ("Boot device 0x%x,%u,%u\n",
+                 ((struct multiboot_tag_bootdev *) tag)->biosdev,
+                 ((struct multiboot_tag_bootdev *) tag)->slice,
+                 ((struct multiboot_tag_bootdev *) tag)->part);
+         break;
+       case MULTIBOOT_TAG_TYPE_MMAP:
+         {
+           multiboot_memory_map_t *mmap;
+
+           printf ("mmap\n");
+      
+           for (mmap = ((struct multiboot_tag_mmap *) tag)->entries;
+                (multiboot_uint8_t *) mmap 
+                  < (multiboot_uint8_t *) tag + tag->size;
+                mmap = (multiboot_memory_map_t *) ((unsigned long) mmap
+                                                   + mmap->size
+                                                   + sizeof (mmap->size)))
+             printf (" size = 0x%x, base_addr = 0x%x%x,"
+                     " length = 0x%x%x, type = 0x%x\n",
+                     (unsigned) mmap->size,
+                     (unsigned) (mmap->addr >> 32),
+                     (unsigned) (mmap->addr & 0xffffffff),
+                     (unsigned) (mmap->len >> 32),
+                     (unsigned) (mmap->len & 0xffffffff),
+                     (unsigned) mmap->type);
+         }
+         break;
+       case MULTIBOOT_TAG_TYPE_FRAMEBUFFER:
+         {
+           multiboot_uint32_t color;
+           unsigned i;
+           struct multiboot_tag_framebuffer *tagfb
+             = (struct multiboot_tag_framebuffer *) tag;
+           void *fb = (void *) (unsigned long) tagfb->common.framebuffer_addr;
+
+           switch (tagfb->common.framebuffer_type)
+             {
+             case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED:
+               {
+                 unsigned best_distance, distance;
+                 struct multiboot_color *palette;
+           
+                 palette = tagfb->framebuffer_palette;
+
+                 color = 0;
+                 best_distance = 4*256*256;
+           
+                 for (i = 0; i < tagfb->framebuffer_palette_num_colors; i++)
+                   {
+                     distance = (0xff - palette[i].blue) 
+                       * (0xff - palette[i].blue)
+                       + palette[i].red * palette[i].red
+                       + palette[i].green * palette[i].green;
+                     if (distance < best_distance)
+                       {
+                         color = i;
+                         best_distance = distance;
+                       }
+                   }
+               }
+               break;
+
+             case MULTIBOOT_FRAMEBUFFER_TYPE_RGB:
+               color = ((1 << tagfb->framebuffer_blue_mask_size) - 1) 
+                 << tagfb->framebuffer_blue_field_position;
+               break;
+
+             case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT:
+               color = '\\' | 0x0100;
+               break;
+
+             default:
+               color = 0xffffffff;
+               break;
+             }
+           
+           for (i = 0; i < tagfb->common.framebuffer_width
+                  && i < tagfb->common.framebuffer_height; i++)
+             {
+               switch (tagfb->common.framebuffer_bpp)
                  {
-                   color = i;
-                   best_distance = distance;
+                 case 8:
+                   {
+                     multiboot_uint8_t *pixel = fb
+                       + tagfb->common.framebuffer_pitch * i + i;
+                     *pixel = color;
+                   }
+                   break;
+                 case 15:
+                 case 16:
+                   {
+                     multiboot_uint16_t *pixel
+                       = fb + tagfb->common.framebuffer_pitch * i + 2 * i;
+                     *pixel = color;
+                   }
+                   break;
+                 case 24:
+                   {
+                     multiboot_uint32_t *pixel
+                       = fb + tagfb->common.framebuffer_pitch * i + 3 * i;
+                     *pixel = (color & 0xffffff) | (*pixel & 0xff000000);
+                   }
+                   break;
+
+                 case 32:
+                   {
+                     multiboot_uint32_t *pixel
+                       = fb + tagfb->common.framebuffer_pitch * i + 4 * i;
+                     *pixel = color;
+                   }
+                   break;
                  }
              }
+           break;
          }
-         break;
-
-       case MULTIBOOT_FRAMEBUFFER_TYPE_RGB:
-         color = ((1 << mbi->framebuffer_blue_mask_size) - 1) 
-           << mbi->framebuffer_blue_field_position;
-         break;
-
-       case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT:
-         color = '\\' | 0x0100;
-         break;
-
-       default:
-         color = 0xffffffff;
-         break;
-       }
-      for (i = 0; i < mbi->framebuffer_width
-            && i < mbi->framebuffer_height; i++)
-       {
-         switch (mbi->framebuffer_bpp)
-           {
-           case 8:
-             {
-               multiboot_uint8_t *pixel = fb + mbi->framebuffer_pitch * i + i;
-               *pixel = color;
-             }
-             break;
-           case 15:
-           case 16:
-             {
-               multiboot_uint16_t *pixel
-                 = fb + mbi->framebuffer_pitch * i + 2 * i;
-               *pixel = color;
-             }
-             break;
-           case 24:
-             {
-               multiboot_uint32_t *pixel
-                 = fb + mbi->framebuffer_pitch * i + 3 * i;
-               *pixel = (color & 0xffffff) | (*pixel & 0xff000000);
-             }
-             break;
-
-           case 32:
-             {
-               multiboot_uint32_t *pixel
-                 = fb + mbi->framebuffer_pitch * i + 4 * i;
-               *pixel = color;
-             }
-             break;
-           }
+
        }
     }
-
+  tag = (struct multiboot_tag *) ((multiboot_uint8_t *) tag + tag->size);
+  printf ("Total mbi size 0x%x\n", (unsigned) tag - addr);
 }    
 
 /* Clear the screen and initialize VIDEO, XPOS and YPOS.  */

=== modified file 'doc/multiboot.texi'
--- doc/multiboot.texi  2010-01-16 16:27:35 +0000
+++ doc/multiboot.texi  2010-01-16 16:33:54 +0000
@@ -514,7 +514,7 @@
 
 @table @samp
 @item EAX
-Must contain the magic value @samp{0x2BADB002}; the presence of this
+Must contain the magic value @samp{0x36d76289}; the presence of this
 value indicates to the operating system that it was loaded by a
 Multiboot-compliant boot loader (e.g. as opposed to another type of
 boot loader that the operating system can also be loaded from).
@@ -577,9 +577,8 @@
 
 
 @node Boot information format
address@hidden Boot information format
-
-FIXME: Split this chapter like the chapter ``OS image format''.
address@hidden Boot information
address@hidden Boot information format
 
 Upon entry to the operating system, the @code{EBX} register contains the
 physical address of a @dfn{Multiboot information} data structure,
@@ -594,206 +593,167 @@
 operating system's responsibility to avoid overwriting this memory until
 it is done using it.
 
-The format of the Multiboot information structure (as defined so far)
-follows:
-
address@hidden
address@hidden
-        +-------------------+
-0       | flags             |    (required)
-        +-------------------+
-4       | mem_lower         |    (present if flags[0] is set)
-8       | mem_upper         |    (present if flags[0] is set)
-        +-------------------+
-12      | boot_device       |    (present if flags[1] is set)
-        +-------------------+
-16      | cmdline           |    (present if flags[2] is set)
-        +-------------------+
-20      | mods_count        |    (present if flags[3] is set)
-24      | mods_addr         |    (present if flags[3] is set)
-        +-------------------+
-28 - 40 | syms              |    (present if flags[4] or
-        |                   |                flags[5] is set)
-        +-------------------+
-44      | mmap_length       |    (present if flags[6] is set)
-48      | mmap_addr         |    (present if flags[6] is set)
-        +-------------------+
-52      | drives_length     |    (present if flags[7] is set)
-56      | drives_addr       |    (present if flags[7] is set)
-        +-------------------+
-60      | config_table      |    (present if flags[8] is set)
-        +-------------------+
-64      | boot_loader_name  |    (present if flags[9] is set)
-        +-------------------+
-68      | apm_table         |    (present if flags[10] is set)
-        +-------------------+
-72      | vbe_control_info  |    (present if flags[11] is set)
-76      | vbe_mode_info     |
-80      | vbe_mode          |
-82      | vbe_interface_seg |
-84      | vbe_interface_off |
-86      | vbe_interface_len |
-        +-------------------+
-88      | framebuffer_addr  |    (present if flags[12] is set)
-96      | framebuffer_pitch |
-100     | framebuffer_width |
-104     | framebuffer_height|
-108     | framebuffer_bpp   |
-109     | framebuffer_type  |
-110-115 | color_info        |
-        +-------------------+
-
address@hidden group
address@hidden example
-
-The first longword indicates the presence and validity of other fields
-in the Multiboot information structure. All as-yet-undefined bits must
-be set to zero by the boot loader. Any set bits that the operating
-system does not understand should be ignored. Thus, the @samp{flags}
-field also functions as a version indicator, allowing the Multiboot
-information structure to be expanded in the future without breaking
-anything.
-
-If bit 0 in the @samp{flags} word is set, then the @samp{mem_*} fields
-are valid. @samp{mem_lower} and @samp{mem_upper} indicate the amount of
address@hidden Basic tags structure
+Boot information consists of fixed part and a series of tags. Fixed part is as 
following:
address@hidden
address@hidden
+        +-------------------+
+0-3     | total_size        |
+        +-------------------+
address@hidden group
address@hidden example
+
address@hidden contains the total size of boot information including
+this field and terminating tag in bytes
+
+Every tag begins with following fields:
+
address@hidden
address@hidden
+        +-------------------+
+0       | type              |
+4-7     | size              |
+        +-------------------+
address@hidden group
address@hidden example
+
address@hidden contains an identifier of contents of the rest of the tag.
address@hidden contains the size of tag including header fields.
+Tags follow one another without any gaps. Tags are terminated by a tag of type 
@samp{0} and size @samp{8}.
+
address@hidden Basic memory information
address@hidden
address@hidden
+        +-------------------+
+0       | type = 4          |
+4       | size = 16         |
+8       | mem_lower         |
+12-15   | mem_upper         |
+        +-------------------+
address@hidden group
address@hidden example
+
+ @samp{mem_lower} and @samp{mem_upper} indicate the amount of
 lower and upper memory, respectively, in kilobytes. Lower memory starts
 at address 0, and upper memory starts at address 1 megabyte. The maximum
 possible value for lower memory is 640 kilobytes. The value returned for
 upper memory is maximally the address of the first upper memory hole
 minus 1 megabyte. It is not guaranteed to be this value.
 
-If bit 1 in the @samp{flags} word is set, then the @samp{boot_device}
-field is valid, and indicates which @sc{bios} disk device the boot
address@hidden BIOS Boot device
address@hidden
address@hidden
+        +-------------------+
+0       | type = 5          |
+4       | size = 20         |
+8       | biosdev           |
+12      | partition         |
+16-19   | sub_parition      |
+        +-------------------+
address@hidden group
address@hidden example
+
+This tag indicates which @sc{bios} disk device the boot
 loader loaded the OS image from. If the OS image was not loaded from a
address@hidden disk, then this field must not be present (bit 3 must be
-clear). The operating system may use this field as a hint for
-determining its own @dfn{root} device, but is not required to. The
address@hidden field is laid out in four one-byte subfields as
-follows:
-
address@hidden
address@hidden
-+-------+-------+-------+-------+
-| part3 | part2 | part1 | drive |
-+-------+-------+-------+-------+
address@hidden group
address@hidden example
-
-The first byte contains the @sc{bios} drive number as understood by the
address@hidden disk, then this tag must not be present. The operating system may
+use this field as a hint for determining its own @dfn{root} device,
+but is not required to.
+
+The @samp{biosdev} contains the @sc{bios} drive number as understood by the
 @sc{bios} INT 0x13 low-level disk interface: e.g. 0x00 for the first
 floppy disk or 0x80 for the first hard disk.
 
-The three remaining bytes specify the boot partition. @samp{part1}
-specifies the @dfn{top-level} partition number, @samp{part2} specifies a
+The three remaining bytes specify the boot partition. @samp{partition}
+specifies the @dfn{top-level} partition number, @samp{sub_partition} specifies 
a
 @dfn{sub-partition} in the top-level partition, etc. Partition numbers
-always start from zero. Unused partition bytes must be set to 0xFF. For
+always start from zero. Unused partition bytes must be set to 0xFFFFFFFF. For
 example, if the disk is partitioned using a simple one-level DOS
-partitioning scheme, then @samp{part1} contains the DOS partition
-number, and @samp{part2} and @samp{part3} are both 0xFF. As another
+partitioning scheme, then @samp{partition} contains the DOS partition
+number, and @samp{sub_partition} if 0xFFFFFF. As another
 example, if a disk is partitioned first into DOS partitions, and then
 one of those DOS partitions is subdivided into several BSD partitions
-using BSD's @dfn{disklabel} strategy, then @samp{part1} contains the DOS
-partition number, @samp{part2} contains the BSD sub-partition within
-that DOS partition, and @samp{part3} is 0xFF.
+using BSD's @dfn{disklabel} strategy, then @samp{partition} contains the DOS
+partition number and @samp{sub_partition} contains the BSD sub-partition within
+that DOS partition.
 
 DOS extended partitions are indicated as partition numbers starting from
 4 and increasing, rather than as nested sub-partitions, even though the
 underlying disk layout of extended partitions is hierarchical in
 nature. For example, if the boot loader boots from the second extended
 partition on a disk partitioned in conventional DOS style, then
address@hidden will be 5, and @samp{part2} and @samp{part3} will both be
-0xFF.
-
-If bit 2 of the @samp{flags} longword is set, the @samp{cmdline} field
-is valid, and contains the physical address of the command line to
-be passed to the kernel. The command line is a normal C-style
-zero-terminated string.
-
-If bit 3 of the @samp{flags} is set, then the @samp{mods} fields
-indicate to the kernel what boot modules were loaded along with the
-kernel image, and where they can be found. @samp{mods_count} contains
-the number of modules loaded; @samp{mods_addr} contains the physical
-address of the first module structure. @samp{mods_count} may be zero,
-indicating no boot modules were loaded, even if bit 1 of @samp{flags} is
-set. Each module structure is formatted as follows:
-
address@hidden
address@hidden
-        +-------------------+
-0       | mod_start         |
-4       | mod_end           |
-        +-------------------+
-8       | string            |
-        +-------------------+
-12      | reserved (0)      |
-        +-------------------+
address@hidden group
address@hidden example
-
-The first two fields contain the start and end addresses of the boot
address@hidden will be 5, and @samp{sub_partiton} will be 0xFFFFFFFF.
+
+
address@hidden Boot command line
address@hidden
address@hidden
+        +-------------------+
+0       | type = 1          |
+4       | size              |
+8-xx    | string            |
+        +-------------------+
address@hidden group
address@hidden example
+
address@hidden contains command line. The command line is a normal C-styl 
+zero-terminated UTF-8 string padded to have length divisible by 4.
+
address@hidden Modules
address@hidden
address@hidden
+        +-------------------+
+0       | type = 3          |
+4       | size              |
+8       | mod_start         |
+12      | mod_end           |
+16-xx   | string            |   
+        +-------------------+
address@hidden group
address@hidden example
+
+This tag indicates to the kernel what boot module was loaded along with the
+kernel image, and where it can be found.
+
+The @samp{mod_start} and @samp{mod_end} contain the start and end addresses of 
the boot
 module itself. The @samp{string} field provides an arbitrary string to
 be associated with that particular boot module; it is a zero-terminated
-ASCII string, just like the kernel command line. The @samp{string} field
-may be 0 if there is no string associated with the module. Typically the
+UTF-8 string, just like the kernel command line. Typically the
 string might be a command line (e.g. if the operating system treats boot
 modules as executable programs), or a pathname (e.g. if the operating
 system treats boot modules as files in a file system), but its exact use
-is specific to the operating system. The @samp{reserved} field must be
-set to 0 by the boot loader and ignored by the operating system.
-
address@hidden:} Bits 4 & 5 are mutually exclusive.
-
-If bit 4 in the @samp{flags} word is set, then the following fields in
-the Multiboot information structure starting at byte 28 are valid:
-
address@hidden
address@hidden
-        +-------------------+
-28      | tabsize           |
-32      | strsize           |
-36      | addr              |
-40      | reserved (0)      |
-        +-------------------+
address@hidden group
address@hidden example
-
-These indicate where the symbol table from an a.out kernel image can be
-found. @samp{addr} is the physical address of the size (4-byte unsigned
-long) of an array of a.out format @dfn{nlist} structures, followed
-immediately by the array itself, then the size (4-byte unsigned long) of
-a set of zero-terminated @sc{ascii} strings (plus sizeof(unsigned long) in
-this case), and finally the set of strings itself. @samp{tabsize} is
-equal to its size parameter (found at the beginning of the symbol
-section), and @samp{strsize} is equal to its size parameter (found at
-the beginning of the string section) of the following string table to
-which the symbol table refers. Note that @samp{tabsize} may be 0,
-indicating no symbols, even if bit 4 in the @samp{flags} word is set.
-
+is specific to the operating system. 
+
+Tag is padded in the way to have size divisible by 4.
+
+One tag appears per module. This tag type may appear multiple times.
+
address@hidden ELF-Symbols
 If bit 5 in the @samp{flags} word is set, then the following fields in
 the Multiboot information structure starting at byte 28 are valid:
 
 @example
 @group
         +-------------------+
-28      | num               |
-32      | size              |
-36      | addr              |
-40      | shndx             |
+0       | type = 9          |
+4       | size              |
+8       | num               |
+12      | entsize           |
+16      | shndx             |
+20-xx   | section headers   |
         +-------------------+
 @end group
 @end example
 
-These indicate where the section header table from an ELF kernel is, the
+This tag contains section header table from an ELF kernel, the
 size of each entry, number of entries, and the string table used as the
 index of names. They correspond to the @samp{shdr_*} entries
 (@samp{shdr_num}, etc.) in the Executable and Linkable Format (@sc{elf})
 specification in the program header. All sections are loaded, and the
 physical address fields of the @sc{elf} section header then refer to where
 the sections are in memory (refer to the i386 @sc{elf} documentation for
-details as to how to read the section header(s)). Note that
address@hidden may be 0, indicating no symbols, even if bit 5 in the
address@hidden word is set.
+details as to how to read the section header(s)).
 
address@hidden Memory map
 If bit 6 in the @samp{flags} word is set, then the @samp{mmap_*} fields
 are valid, and indicate the address and length of a buffer containing a
 memory map of the machine provided by the @sc{bios}. @samp{mmap_addr} is
@@ -823,86 +783,52 @@
 The map provided is guaranteed to list all standard @sc{ram} that should
 be available for normal use.
 
-If bit 7 in the @samp{flags} is set, then the @samp{drives_*} fields
-are valid, and indicate the address of the physical address of the first
-drive structure and the size of drive structures. @samp{drives_addr}
-is the address, and @samp{drives_length} is the total size of drive
-structures. Note that @samp{drives_length} may be zero. Each drive
-structure is formatted as follows:
-
+The corresponding tag is
 @example
 @group
         +-------------------+
-0       | size              |
-        +-------------------+
-4       | drive_number      |
-        +-------------------+
-5       | drive_mode        |
-        +-------------------+
-6       | drive_cylinders   |
-8       | drive_heads       |
-9       | drive_sectors     |
-        +-------------------+
-10 - xx | drive_ports       |
+0       | type = 6          |
+4       | size              |
+8-xx    | entries           |
         +-------------------+
 @end group
 @end example
 
-The @samp{size} field specifies the size of this structure. The size
-varies, depending on the number of ports. Note that the size may not be
-equal to (10 + 2 * the number of ports), because of an alignment.
-
-The @samp{drive_number} field contains the BIOS drive number. The
address@hidden field represents the access mode used by the boot
-loader. Currently, the following modes are defined:
-
address@hidden @samp
address@hidden 0
-CHS mode (traditional cylinder/head/sector addressing mode).
-
address@hidden 1
-LBA mode (Logical Block Addressing mode).
address@hidden table
-
-The three fields, @samp{drive_cylinders}, @samp{drive_heads} and
address@hidden, indicate the geometry of the drive detected by the
address@hidden @samp{drive_cylinders} contains the number of the
-cylinders. @samp{drive_heads} contains the number of the
-heads. @samp{drive_sectors} contains the number of the sectors per
-track.
-
-The @samp{drive_ports} field contains the array of the I/O ports used
-for the drive in the @sc{bios} code. The array consists of zero or more
-unsigned two-bytes integers, and is terminated with zero. Note that the
-array may contain any number of I/O ports that are not related to the
-drive actually (such as @sc{dma} controller's ports).
-
-If bit 8 in the @samp{flags} is set, then the @samp{config_table} field
-is valid, and indicates the address of the @sc{rom} configuration table
-returned by the @dfn{GET CONFIGURATION} @sc{bios} call. If the @sc{bios}
-call fails, then the size of the table must be @emph{zero}.
-
address@hidden Boot loader name
 If bit 9 in the @samp{flags} is set, the @samp{boot_loader_name} field
 is valid, and contains the physical address of the name of a boot
 loader booting the kernel. The name is a normal C-style zero-terminated
 string.
 
-If bit 10 in the @samp{flags} is set, the @samp{apm_table} field is
-valid, and contains the physical address of an @sc{apm} table defined as
-below:
-
+Corresponding tag is:
address@hidden
address@hidden
+        +-------------------+
+0       | type = 2          |
+4       | size              |
+8-xx    | string            |
+        +-------------------+
address@hidden group
address@hidden example
+
address@hidden contains zero-terminated UTF-8 string padded to have length 
divisible by 4.
+
address@hidden APM table
+The tag type 10 contains @sc{apm} table
 @example
 @group
         +----------------------+
-0       | version              |
-2       | cseg                 |
-4       | offset               |
-8       | cseg_16              |
-10      | dseg                 |
-12      | flags                |
-14      | cseg_len             |
-16      | cseg_16_len          |
-18      | dseg_len             |
+0       | type = 10            |
+4       | size                 |
+8       | version              |
+10      | cseg                 |
+12      | offset               |
+16      | cseg_16              |
+18      | dseg                 |
+20      | flags                |
+22      | cseg_len             |
+24      | cseg_16_len          |
+26-27   | dseg_len             |
         +----------------------+
 @end group
 @end example
@@ -919,10 +845,24 @@
 @uref{http://www.microsoft.com/hwdev/busbios/amp_12.htm, Advanced Power
 Management (APM) BIOS Interface Specification}, for more information.
 
-If bit 11 in the @samp{flags} is set, the @sc{vbe} table is available.
address@hidden VBE info
address@hidden
address@hidden
+        +-------------------+
+0       | type = 7          |
+4       | size = 784        |
+8       | vbe_mode          |
+10      | vbe_interface_seg |
+12      | vbe_interface_off |
+14      | vbe_interface_len |
+16      | vbe_control_info  |
+528-783 | vbe_mode_info     |
+        +-------------------+
address@hidden group
address@hidden example
 
 The fields @samp{vbe_control_info} and @samp{vbe_mode_info} contain
-the physical addresses of @sc{vbe} control information returned by the
address@hidden control information returned by the
 @sc{vbe} Function 00h and @sc{vbe} mode information returned by the
 @sc{vbe} Function 01h, respectively.
 
@@ -937,62 +877,61 @@
 use the new protected mode interface, you will have to find the table
 yourself.
 
-The fields for the graphics table are designed for @sc{vbe}, but
-Multiboot boot loaders may simulate @sc{vbe} on address@hidden modes, as
-if they were @sc{vbe} modes.
-
-If bit 12 in the @samp{flags} is set, the @sc{Framebuffer} table is available.
-
-The field @samp{framebuffer_addr} contains framebuffer physical address. This
-field is 64-bit wide but bootloader @dfn{should} set it under 4 GiB if possible
-for compatibility with kernels which aren't aware of PAE or AMD64. The field
address@hidden contains the framebuffer pitch in bytes. The fields
address@hidden, @samp{framebuffer_height} contain the framebuffer
-dimensions in pixels. The field @samp{framebuffer_bpp} contains the number of
-bits per pixel. If @samp{framebuffer_type} is set to @samp{0} it means
-indexed color will be used. In this case color_info is defined as follows:
address@hidden
address@hidden
-        +----------------------------------+
-110     | framebuffer_palette_addr         |
-114     | framebuffer_palette_num_colors   |
-        +----------------------------------+
address@hidden group
address@hidden example
address@hidden contains the address of the color palette,
-which is an array of color descriptors. Each color descriptor has the
-following structure:
address@hidden Framebuffer info
address@hidden
address@hidden
+        +--------------------+
+0       | type = 8           |
+4       | size               |
+8       | framebuffer_addr   |
+16      | framebuffer_pitch  |
+20      | framebuffer_width  |
+24      | framebuffer_height |
+28      | framebuffer_bpp    |
+29      | framebuffer_type   |
+30      | color_info         |
+        +--------------------+
address@hidden group
address@hidden example
+
+The field @samp{framebuffer_addr} contains framebuffer physical address. This 
field is 64-bit wide but bootloader @dfn{should} set it under 4GiB if possible 
for compatibility with payloads which aren't aware of PAE or amd64. The field 
@samp{framebuffer_pitch} contains pitch in bytes. The fields 
@samp{framebuffer_width}, @samp{framebuffer_height} contain framebuffer 
dimensions in pixels. The field @samp{framebuffer_bpp} contains number of bits 
per pixel. If @samp{framebuffer_type} is set to 0 it means indexed color. In 
this case color_info is defined as follows:
address@hidden
address@hidden
+        +----------------------------------+
+30      | framebuffer_palette_num_colors   |
+34-xx   | framebuffer_palette              |
+        +----------------------------------+
address@hidden group
address@hidden example
address@hidden is an array of colour descriptors.
+Each colour descriptor has following structure:
 @example
 @group
         +-------------+
 0       | red_value   |
 1       | green_value |
-2       | blue_value  |
+2-2     | blue_value  |
         +-------------+
 @end group
 @end example
-If @samp{framebuffer_type} is set to @samp{1} it means direct RGB color will
-be used. Then color_type is defined as follows:
+If @samp{framebuffer_type} is set to @samp{1} it means direct RGB color.
+Then color_type is defined as follows:
 
 @example
 @group
-        +----------------------------------+
-110     | framebuffer_red_field_position   |
-111     | framebuffer_red_mask_size        |
-112     | framebuffer_green_field_position |
-113     | framebuffer_green_mask_size      |
-114     | framebuffer_blue_field_position  |
-115     | framebuffer_blue_mask_size       |
-        +----------------------------------+
+       +----------------------------------+
+30     | framebuffer_red_field_position   |
+31     | framebuffer_red_mask_size        |
+32     | framebuffer_green_field_position |
+33     | framebuffer_green_mask_size      |
+34     | framebuffer_blue_field_position  |
+35-35  | framebuffer_blue_mask_size       |
+       +----------------------------------+
 @end group
 @end example
 
-If @samp{framebuffer_type} is set to @samp{2} it means EGA-standard text mode
-will be used. In this case @samp{framebuffer_width} and
address@hidden are expressed in characters instead of pixels.
address@hidden is equal to 16 (bits per character) and
address@hidden is expressed in bytes per text line.
-All further values of @samp{framebuffer_type} are reserved for future 
expansion.
+If @samp{framebuffer_type} is set to @samp{2} it means EGA text. In this case 
@samp{framebuffer_width} and @samp{framebuffer_height} are expressed in 
characters and not in pixels. @samp{framebuffer_bpp} is equal 16 (16 bits per 
character) and @samp{framebuffer_pitch} is expressed in bytes per text line.
+All further values of @samp{framebuffer_type} are reserved for future expansion
 
 @node Examples
 @chapter Examples

=== modified file 'doc/multiboot2.h'
--- doc/multiboot2.h    2010-01-16 16:27:35 +0000
+++ doc/multiboot2.h    2010-01-16 16:31:40 +0000
@@ -51,42 +51,17 @@
 /* This flag indicates the use of the address fields in the header.  */
 #define MULTIBOOT_AOUT_KLUDGE                  0x00010000
 
-/* Flags to be set in the 'flags' member of the multiboot info structure.  */
-
-/* is there basic lower/upper memory information? */
-#define MULTIBOOT_INFO_MEMORY                  0x00000001
-/* is there a boot device set? */
-#define MULTIBOOT_INFO_BOOTDEV                 0x00000002
-/* is the command-line defined? */
-#define MULTIBOOT_INFO_CMDLINE                 0x00000004
-/* are there modules to do something with? */
-#define MULTIBOOT_INFO_MODS                    0x00000008
-
-/* These next two are mutually exclusive */
-
-/* is there a symbol table loaded? */
-#define MULTIBOOT_INFO_AOUT_SYMS               0x00000010
-/* is there an ELF section header table? */
-#define MULTIBOOT_INFO_ELF_SHDR                        0X00000020
-
-/* is there a full memory map? */
-#define MULTIBOOT_INFO_MEM_MAP                 0x00000040
-
-/* Is there drive info?  */
-#define MULTIBOOT_INFO_DRIVE_INFO              0x00000080
-
-/* Is there a config table?  */
-#define MULTIBOOT_INFO_CONFIG_TABLE            0x00000100
-
-/* Is there a boot loader name?  */
-#define MULTIBOOT_INFO_BOOT_LOADER_NAME                0x00000200
-
-/* Is there a APM table?  */
-#define MULTIBOOT_INFO_APM_TABLE               0x00000400
-
-/* Is there video information?  */
-#define MULTIBOOT_INFO_VBE_INFO                        0x00000800
-#define MULTIBOOT_INFO_FRAMEBUFFER_INFO                0x00001000
+#define MULTIBOOT_TAG_TYPE_END               0
+#define MULTIBOOT_TAG_TYPE_CMDLINE           1
+#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME  2
+#define MULTIBOOT_TAG_TYPE_MODULE            3
+#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO     4
+#define MULTIBOOT_TAG_TYPE_BOOTDEV           5
+#define MULTIBOOT_TAG_TYPE_MMAP              6
+#define MULTIBOOT_TAG_TYPE_VBE               7
+#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER       8
+#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS      9
+#define MULTIBOOT_TAG_TYPE_APM              10
 
 #ifndef ASM_FILE
 
@@ -120,26 +95,6 @@
   multiboot_uint32_t depth;
 };
 
-/* The symbol table for a.out.  */
-struct multiboot_aout_symbol_table
-{
-  multiboot_uint32_t tabsize;
-  multiboot_uint32_t strsize;
-  multiboot_uint32_t addr;
-  multiboot_uint32_t reserved;
-};
-typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t;
-
-/* The section header table for ELF.  */
-struct multiboot_elf_section_header_table
-{
-  multiboot_uint32_t num;
-  multiboot_uint32_t size;
-  multiboot_uint32_t addr;
-  multiboot_uint32_t shndx;
-};
-typedef struct multiboot_elf_section_header_table 
multiboot_elf_section_header_table_t;
-
 struct multiboot_color
 {
   multiboot_uint8_t red;
@@ -147,75 +102,114 @@
   multiboot_uint8_t blue;
 };
 
-struct multiboot_info
-{
-  /* Multiboot info version number */
-  multiboot_uint32_t flags;
-
-  /* Available memory from BIOS */
+struct multiboot_mmap_entry
+{
+  multiboot_uint32_t size;
+  multiboot_uint64_t addr;
+  multiboot_uint64_t len;
+#define MULTIBOOT_MEMORY_AVAILABLE             1
+#define MULTIBOOT_MEMORY_RESERVED              2
+  multiboot_uint32_t type;
+} __attribute__((packed));
+typedef struct multiboot_mmap_entry multiboot_memory_map_t;
+
+struct multiboot_tag
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+};
+
+struct multiboot_tag_string
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  char string[0];
+};
+
+struct multiboot_tag_module
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint32_t mod_start;
+  multiboot_uint32_t mod_end;
+  char cmdline[0];
+};
+
+struct multiboot_tag_basic_meminfo
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
   multiboot_uint32_t mem_lower;
   multiboot_uint32_t mem_upper;
-
-  /* "root" partition */
-  multiboot_uint32_t boot_device;
-
-  /* Kernel command line */
-  multiboot_uint32_t cmdline;
-
-  /* Boot-Module list */
-  multiboot_uint32_t mods_count;
-  multiboot_uint32_t mods_addr;
-
-  union
-  {
-    multiboot_aout_symbol_table_t aout_sym;
-    multiboot_elf_section_header_table_t elf_sec;
-  } u;
-
-  /* Memory Mapping buffer */
-  multiboot_uint32_t mmap_length;
-  multiboot_uint32_t mmap_addr;
-
-  /* Drive Info buffer */
-  multiboot_uint32_t drives_length;
-  multiboot_uint32_t drives_addr;
-
-  /* ROM configuration table */
-  multiboot_uint32_t config_table;
-
-  /* Boot Loader Name */
-  multiboot_uint32_t boot_loader_name;
-
-  /* APM table */
-  multiboot_uint32_t apm_table;
-
-  /* Video */
-  multiboot_uint32_t vbe_control_info;
-  multiboot_uint32_t vbe_mode_info;
+};
+
+struct multiboot_tag_bootdev
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint32_t biosdev;
+  multiboot_uint32_t slice;
+  multiboot_uint32_t part;
+};
+
+struct multiboot_tag_mmap
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  struct multiboot_mmap_entry entries[0];  
+};
+
+struct multiboot_vbe_info_block
+{
+  multiboot_uint8_t external_specification[512];
+};
+
+struct multiboot_vbe_mode_info_block
+{
+  multiboot_uint8_t external_specification[256];
+};
+
+struct multiboot_tag_vbe
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+
   multiboot_uint16_t vbe_mode;
   multiboot_uint16_t vbe_interface_seg;
   multiboot_uint16_t vbe_interface_off;
   multiboot_uint16_t vbe_interface_len;
 
+  struct multiboot_vbe_info_block vbe_control_info;
+  struct multiboot_vbe_mode_info_block vbe_mode_info;
+};
+
+struct multiboot_tag_framebuffer_common
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+
   multiboot_uint64_t framebuffer_addr;
   multiboot_uint32_t framebuffer_pitch;
   multiboot_uint32_t framebuffer_width;
   multiboot_uint32_t framebuffer_height;
   multiboot_uint8_t framebuffer_bpp;
-#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED     0
-#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB         1
+#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
+#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB     1
 #define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT    2
   multiboot_uint8_t framebuffer_type;
+};
+
+struct multiboot_tag_framebuffer
+{
+  struct multiboot_tag_framebuffer_common common;
+
   union
   {
-    /* Indexed color.  */
     struct
     {
-      struct multiboot_color *framebuffer_palette_addr;
       multiboot_uint16_t framebuffer_palette_num_colors;
+      struct multiboot_color framebuffer_palette[0];
     };
-
-    /* Direct RGB color.  */
     struct
     {
       multiboot_uint8_t framebuffer_red_field_position;
@@ -227,32 +221,31 @@
     };
   };
 };
-typedef struct multiboot_info multiboot_info_t;
-
-struct multiboot_mmap_entry
-{
-  multiboot_uint32_t size;
-  multiboot_uint64_t addr;
-  multiboot_uint64_t len;
-#define MULTIBOOT_MEMORY_AVAILABLE             1
-#define MULTIBOOT_MEMORY_RESERVED              2
-  multiboot_uint32_t type;
-} __attribute__((packed));
-typedef struct multiboot_mmap_entry multiboot_memory_map_t;
-
-struct multiboot_mod_list
-{
-  /* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */
-  multiboot_uint32_t mod_start;
-  multiboot_uint32_t mod_end;
-
-  /* Module command line */
-  multiboot_uint32_t cmdline;
-
-  /* padding to take it to 16 bytes (must be zero) */
-  multiboot_uint32_t pad;
-};
-typedef struct multiboot_mod_list multiboot_module_t;
+
+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 */
 

Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]