--- /dev/null	2012-08-31 05:08:50.000000000 +0400
+++ new/grub/grub-core/commands/menu_managing.c	2012-08-31 05:08:50.915580323 +0400
@@ -0,0 +1,200 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2012 Daniil Lunev
+ *
+ *  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/>.
+ */
+
+#define VALUE_SIZE 512
+
+typedef struct entries entries;
+struct entries {
+  entries *next;
+  char ** entry_info;
+};
+
+enum param_consts {
+  ENTRY_NAME,
+  POOL_UUID,
+  POOL_LABEL,
+  DATA_SET,
+  KERNEL_PATH,
+  KERNEL_OPTIONS,
+  BA_PATH,
+  DOLLAR_KERNEL_PATH,
+  DOLLAR_BA_PATH,
+};
+
+static const char * params_list[] = {
+  "entry_name",
+  "pool_uuid",
+  "pool_label",
+  "data_set",
+  "kernel_path",
+  "kernel_options",
+  "module",
+  "kernel_path$",
+  "module$",
+  NULL
+};
+
+static grub_err_t
+init_entries(entries ** menu_entries)
+{
+  (*menu_entries) = (entries*) grub_zalloc(sizeof (menu_entries));
+  if (! *menu_entries)
+    return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("memory can not be allocated"));
+  return 0;
+}
+
+static entries * 
+new_entry(char * name, entries * entry_list)
+{
+  unsigned int i;
+
+  if (entry_list->next)
+    do {
+      entry_list = entry_list->next;
+      if (!grub_strcmp(name, entry_list->entry_info[0]))
+        return entry_list;
+    } while (entry_list->next);
+  entry_list->next = (entries*) grub_zalloc(sizeof(entries));
+  if (! entry_list->next)
+    return NULL;
+  entry_list = entry_list->next;
+  entry_list->entry_info = (char**) grub_zalloc(sizeof(params_list));
+  for (i = 0; i < sizeof(params_list) / sizeof(*params_list); i++) {
+    entry_list->entry_info[i] = (char *) grub_zalloc(VALUE_SIZE);
+    if (! entry_list->entry_info[i]) 
+      return NULL;
+  }
+  grub_strcpy(entry_list->entry_info[0], name);
+  return entry_list;
+}
+
+static void
+clear_entries(entries * entry_list)
+{
+  entries * next;
+  unsigned int i;
+
+  next = entry_list->next;
+  grub_free(entry_list);
+  entry_list = next;
+
+  while (entry_list) {
+    next = entry_list->next;
+    if (entry_list->entry_info) {
+      for (i = 0; i < sizeof(params_list) / sizeof(*params_list); i++)
+        if (entry_list->entry_info[i])
+          grub_free(entry_list->entry_info[i]);
+      grub_free(entry_list->entry_info);
+    }
+    grub_free(entry_list);
+    entry_list = next;
+  }
+}
+
+static grub_err_t
+add_entries(entries * menu_entries)
+{
+  grub_err_t err;
+  char cl1[] = "os";
+  char cl2[] = "illumos";
+  char * class[] = {cl1, cl2, NULL};
+  char * argv[] = { NULL, NULL };
+  char id[512];
+  char * entry_source = NULL;
+  char * data_set;
+  char entry_template[] = 
+    "insmod part_sunpc\n"
+    "insmod part_msdos\n"
+    "insmod zfs\n"
+    "insmod gzio\n"
+    "if cpuid -l ; then\n"
+    "  ISADIR=amd64\n"
+    "else\n"
+    "  ISADIR=\n"
+    "fi\n";
+
+  menu_entries = menu_entries->next;
+  while (menu_entries) {
+    argv[0] = grub_strdup(menu_entries->entry_info[ENTRY_NAME]);
+    if (!argv[0])
+      return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("memory can not be allocated"));
+    entry_source = (char*) grub_zalloc(2048);
+
+    if (!entry_source)
+      return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("memory can not be allocated"));
+
+    if (menu_entries->entry_info[DATA_SET][0] != 0)
+      data_set = grub_strchr(menu_entries->entry_info[DATA_SET], '/');
+    else
+      data_set = grub_strdup("$ZFS_DATASET");
+    grub_strcpy(entry_source, entry_template);
+    if (menu_entries->entry_info[POOL_UUID][0]) {
+      grub_strcat(entry_source, "search --no-floppy --zfs-mirror --fs-uuid --set=root ");
+      grub_strcat(entry_source, menu_entries->entry_info[POOL_UUID]);
+    } else {
+      grub_strcat(entry_source, "search --no-floppy --zfs-mirror --label --set=root ");
+      grub_strcat(entry_source, menu_entries->entry_info[POOL_LABEL]);
+    }
+    grub_strcat(entry_source, "\n");
+    grub_strcat(entry_source, "zfs-bootfs ($root)");
+    if (menu_entries->entry_info[DATA_SET][0] != 0) {
+      grub_strcat(entry_source, data_set);
+      grub_strcat(entry_source, " ZFS_BOOTFS\n");
+    } else {
+      grub_strcat(entry_source, "default ZFS_BOOTFS ZFS_DATASET\n");
+    }
+    grub_strcat(entry_source, "multiboot ($root)");
+    if (! menu_entries->entry_info[DOLLAR_KERNEL_PATH][0]) {
+      grub_strcat(entry_source, data_set);
+      grub_strcat(entry_source, "/@");
+      grub_strcat(entry_source, menu_entries->entry_info[KERNEL_PATH]);
+      grub_strcat(entry_source, " ");
+      grub_strcat(entry_source, menu_entries->entry_info[KERNEL_PATH]);
+    } else {
+      grub_strcat(entry_source, menu_entries->entry_info[DOLLAR_KERNEL_PATH]);
+    }
+    grub_strcat(entry_source, " ");
+    grub_strcat(entry_source, menu_entries->entry_info[KERNEL_OPTIONS]);
+    grub_strcat(entry_source, "\n");
+    grub_strcat(entry_source, "module ($root)");
+    if (! menu_entries->entry_info[DOLLAR_KERNEL_PATH][0]) {
+      grub_strcat(entry_source, data_set);
+      grub_strcat(entry_source, "/@");
+      grub_strcat(entry_source, menu_entries->entry_info[BA_PATH]);
+      grub_strcat(entry_source, " ");
+      grub_strcat(entry_source, menu_entries->entry_info[BA_PATH]);
+    } else {
+      grub_strcat(entry_source, menu_entries->entry_info[DOLLAR_BA_PATH]);
+    }
+
+    grub_strcpy(id, argv[0]);
+    grub_strcat(id, "-");
+    grub_strcat(id, menu_entries->entry_info[POOL_UUID]);
+
+    err = grub_normal_add_menu_entry (2, (const char **) argv, class, id,
+                NULL,  NULL,  NULL, entry_source, 0);
+
+    if (err)
+      return err;
+    
+    grub_free(argv[0]);
+    menu_entries = menu_entries->next;
+  }
+  grub_free(entry_source);
+  return 0;
+}
