]> glassweightruler.freedombox.rocks Git - Ventoy.git/commitdiff
1. Boot menu over serial supported
authorlongpanda <admin@ventoy.net>
Fri, 7 Aug 2020 14:23:27 +0000 (22:23 +0800)
committerlongpanda <admin@ventoy.net>
Fri, 7 Aug 2020 14:25:16 +0000 (22:25 +0800)
2. Optimization for booting Solus
3. Optimization for booting .efi file
4. support deepin-live iso
5. support Endless OS
6. framework for booting .img file

54 files changed:
EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.c
EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.h
EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/VentoyProtocol.c
GRUB2/MOD_SRC/grub-2.04/grub-core/Makefile.core.def
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/blscfg.c [new file with mode: 0644]
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/legacycfg.c [new file with mode: 0644]
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/loadenv.c [new file with mode: 0644]
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/loadenv.h [new file with mode: 0644]
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/menuentry.c [new file with mode: 0644]
GRUB2/MOD_SRC/grub-2.04/grub-core/kern/main.c
GRUB2/MOD_SRC/grub-2.04/grub-core/loader/i386/linux.c [new file with mode: 0644]
GRUB2/MOD_SRC/grub-2.04/grub-core/normal/main.c [new file with mode: 0644]
GRUB2/MOD_SRC/grub-2.04/grub-core/normal/menu.c
GRUB2/MOD_SRC/grub-2.04/grub-core/normal/menu_text.c
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy.c
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_def.h
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_linux.c
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_plugin.c
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_unix.c [new file with mode: 0644]
GRUB2/MOD_SRC/grub-2.04/include/grub/compiler.h [new file with mode: 0644]
GRUB2/MOD_SRC/grub-2.04/include/grub/kernel.h [new file with mode: 0644]
GRUB2/MOD_SRC/grub-2.04/include/grub/menu.h [new file with mode: 0644]
GRUB2/MOD_SRC/grub-2.04/include/grub/normal.h [new file with mode: 0644]
IMG/cpio/sbin/init
IMG/cpio/ventoy/hook/default/10-dm.rules [new file with mode: 0644]
IMG/cpio/ventoy/hook/ventoy-hook-lib.sh
IMG/cpio/ventoy/hook/ventoy-os-lib.sh
IMG/cpio/ventoy/init
IMG/cpio/ventoy/init_chain [new file with mode: 0644]
IMG/cpio/ventoy/init_loop [new file with mode: 0644]
IMG/cpio/ventoy/loop/deepin/ventoy-disk.sh [new file with mode: 0644]
IMG/cpio/ventoy/loop/deepin/ventoy-init.sh [new file with mode: 0644]
IMG/cpio/ventoy/loop/endless/ventoy-hook.sh [new file with mode: 0644]
IMG/cpio/ventoy/loop/endless/ventoy-inotifyd-hook.sh [new file with mode: 0644]
IMG/cpio/ventoy/loop/endless/ventoy-inotifyd-start.sh [new file with mode: 0644]
IMG/cpio/ventoy/ventoy_chain.sh [moved from IMG/cpio/ventoy/ventoy.sh with 99% similarity]
IMG/cpio/ventoy/ventoy_loop.sh [new file with mode: 0644]
IMG/mkcpio.sh
INSTALL/CreatePersistentImg.sh
INSTALL/EFI/BOOT/grubx64_real.efi
INSTALL/grub/grub.cfg
INSTALL/grub/i386-pc/blscfg.mod [new file with mode: 0644]
INSTALL/grub/i386-pc/command.lst
INSTALL/grub/i386-pc/core.img
INSTALL/grub/i386-pc/legacycfg.mod
INSTALL/grub/i386-pc/moddep.lst
INSTALL/grub/x86_64-efi/blscfg.mod [new file with mode: 0644]
INSTALL/grub/x86_64-efi/command.lst
INSTALL/grub/x86_64-efi/legacycfg.mod
INSTALL/grub/x86_64-efi/moddep.lst
INSTALL/grub/x86_64-efi/normal.mod
INSTALL/ventoy/ventoy.cpio
INSTALL/ventoy/ventoy_efiboot.img.xz [new file with mode: 0644]
INSTALL/ventoy/ventoy_x64.efi

index bd28ca268993583f1c448cd0721db237ff254b7b..6cd64636e3230036826179259103f462c5dfa999 100644 (file)
@@ -331,7 +331,7 @@ EFI_STATUS EFIAPI ventoy_save_ramdisk_param(VOID)
     Status = gRT->SetVariable(L"VentoyRamDisk", &VarGuid, 
                   EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
                   sizeof(g_ramdisk_param), &(g_ramdisk_param));
-    debug("set efi variable %r", Status);
+    debug("set ramdisk variable %r", Status);
 
     return Status;
 }
@@ -663,17 +663,22 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
     size = StrDecimalToUintn(pPos + 5);
 
     debug("memory addr:%p size:%lu", chain, size);
-    
-    g_chain = AllocatePool(size);
-    CopyMem(g_chain, chain, size);
 
     if (StrStr(pCmdLine, L"memdisk"))
     {
-        g_iso_buf_size = size;
+        g_iso_data_buf = (UINT8 *)chain + sizeof(ventoy_chain_head);
+        g_iso_buf_size = size - sizeof(ventoy_chain_head);
+        debug("memdisk mode iso_buf_size:%u", g_iso_buf_size);
+
+        g_chain = chain;
         gMemdiskMode = TRUE;
     }
     else
     {
+        debug("This is normal mode");
+        g_chain = AllocatePool(size);
+        CopyMem(g_chain, chain, size);
+    
         g_chunk = (ventoy_img_chunk *)((char *)g_chain + g_chain->img_chunk_offset);
         g_img_chunk_num = g_chain->img_chunk_num;
         g_override_chunk = (ventoy_override_chunk *)((char *)g_chain + g_chain->override_chunk_offset);
@@ -725,6 +730,8 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
         }
     }
 
+    ventoy_debug_pause();
+
     FreePool(pCmdLine);
     return EFI_SUCCESS;
 }
@@ -942,15 +949,29 @@ EFI_STATUS EFIAPI VentoyEfiMain
 
     if (gMemdiskMode)
     {
-        g_ramdisk_param.PhyAddr = (UINT64)(UINTN)g_chain;
+        g_ramdisk_param.PhyAddr = (UINT64)(UINTN)g_iso_data_buf;
         g_ramdisk_param.DiskSize = (UINT64)g_iso_buf_size;
 
         ventoy_save_ramdisk_param();
+
+        if (gLoadIsoEfi)
+        {
+            ventoy_find_iso_disk(ImageHandle);
+            ventoy_find_iso_disk_fs(ImageHandle);
+            ventoy_load_isoefi_driver(ImageHandle);
+        }
         
         ventoy_install_blockio(ImageHandle, g_iso_buf_size);
+        ventoy_debug_pause();
+
         Status = ventoy_boot(ImageHandle);
         
         ventoy_delete_ramdisk_param();
+
+        if (gLoadIsoEfi && gBlockData.IsoDriverImage)
+        {
+            gBS->UnloadImage(gBlockData.IsoDriverImage);
+        }
     }
     else
     {
index 2e2ab031738116329c7b8378b37be92caa3d5e4c..250da0edd8d12abb23b128bbca0a499fecb4216c 100644 (file)
@@ -339,6 +339,7 @@ extern ventoy_sector_flag *g_sector_flag;
 extern UINT32 g_sector_flag_num;
 extern BOOLEAN gMemdiskMode;
 extern UINTN g_iso_buf_size;
+extern UINT8 *g_iso_data_buf;
 extern ventoy_grub_param_file_replace *g_file_replace_list;
 extern BOOLEAN g_fixup_iso9660_secover_enable;
 extern EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *g_con_simple_input_ex;
index 004c83f9f8d374345b1fc808ee1221c49b791a58..bb0e95e191c46df7c296f9d758c6337a1e1cf60f 100644 (file)
@@ -36,6 +36,7 @@
 #include <Protocol/SimpleFileSystem.h>
 #include <Ventoy.h>
 
+UINT8 *g_iso_data_buf = NULL;
 UINTN g_iso_buf_size = 0;
 BOOLEAN gMemdiskMode = FALSE;
 
@@ -254,7 +255,7 @@ EFI_STATUS EFIAPI ventoy_block_io_ramdisk_read
     (VOID)This;
     (VOID)MediaId;
 
-    CopyMem(Buffer, (char *)g_chain + (Lba * 2048), BufferSize);
+    CopyMem(Buffer, g_iso_data_buf + (Lba * 2048), BufferSize);
     
     if (g_blockio_start_record_bcd && FALSE == g_blockio_bcd_read_done)
     {
index e8d4a7f4585e617251df8f543053865f8728b0aa..4ac0746f458b959e031fa35f05dd4b2fd436fcda 100644 (file)
@@ -809,6 +809,16 @@ module = {
   common = commands/blocklist.c;
 };
 
+module = {
+  name = blscfg;
+  common = commands/blscfg.c;
+  common = commands/loadenv.h;
+  enable = powerpc_ieee1275;
+  enable = efi;
+  enable = i386_pc;
+  enable = emu;
+};
+
 module = {
   name = boot;
   common = commands/boot.c;
@@ -986,6 +996,7 @@ module = {
 module = {
   name = loadenv;
   common = commands/loadenv.c;
+  common = commands/loadenv.h;
   common = lib/envblk.c;
 };
 
diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/commands/blscfg.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/commands/blscfg.c
new file mode 100644 (file)
index 0000000..55ee2be
--- /dev/null
@@ -0,0 +1,1111 @@
+/*-*- Mode: C; c-basic-offset: 2; indent-tabs-mode: t -*-*/
+
+/* bls.c - implementation of the boot loader spec */
+
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *
+ *  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/list.h>
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/extcmd.h>
+#include <grub/i18n.h>
+#include <grub/fs.h>
+#include <grub/env.h>
+#include <grub/file.h>
+#include <grub/normal.h>
+#include <grub/lib/envblk.h>
+
+#include <stdbool.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+#include "loadenv.h"
+
+#define GRUB_BLS_CONFIG_PATH "/loader/entries/"
+#ifdef GRUB_MACHINE_EMU
+#define GRUB_BOOT_DEVICE "/boot"
+#else
+#define GRUB_BOOT_DEVICE "($root)"
+#endif
+
+struct keyval
+{
+  const char *key;
+  char *val;
+};
+
+static struct bls_entry *entries = NULL;
+
+#define FOR_BLS_ENTRIES(var) FOR_LIST_ELEMENTS (var, entries)
+
+static int bls_add_keyval(struct bls_entry *entry, char *key, char *val)
+{
+  char *k, *v;
+  struct keyval **kvs, *kv;
+  int new_n = entry->nkeyvals + 1;
+
+  kvs = grub_realloc (entry->keyvals, new_n * sizeof (struct keyval *));
+  if (!kvs)
+    return grub_error (GRUB_ERR_OUT_OF_MEMORY,
+                      "couldn't find space for BLS entry");
+  entry->keyvals = kvs;
+
+  kv = grub_malloc (sizeof (struct keyval));
+  if (!kv)
+    return grub_error (GRUB_ERR_OUT_OF_MEMORY,
+                      "couldn't find space for BLS entry");
+
+  k = grub_strdup (key);
+  if (!k)
+    {
+      grub_free (kv);
+      return grub_error (GRUB_ERR_OUT_OF_MEMORY,
+                        "couldn't find space for BLS entry");
+    }
+
+  v = grub_strdup (val);
+  if (!v)
+    {
+      grub_free (k);
+      grub_free (kv);
+      return grub_error (GRUB_ERR_OUT_OF_MEMORY,
+                        "couldn't find space for BLS entry");
+    }
+
+  kv->key = k;
+  kv->val = v;
+
+  entry->keyvals[entry->nkeyvals] = kv;
+  grub_dprintf("blscfg", "new keyval at %p:%s:%s\n", entry->keyvals[entry->nkeyvals], k, v);
+  entry->nkeyvals = new_n;
+
+  return 0;
+}
+
+/* Find they value of the key named by keyname.  If there are allowed to be
+ * more than one, pass a pointer to an int set to -1 the first time, and pass
+ * the same pointer through each time after, and it'll return them in sorted
+ * order as defined in the BLS fragment file */
+static char *bls_get_val(struct bls_entry *entry, const char *keyname, int *last)
+{
+  int idx, start = 0;
+  struct keyval *kv = NULL;
+
+  if (last)
+    start = *last + 1;
+
+  for (idx = start; idx < entry->nkeyvals; idx++) {
+    kv = entry->keyvals[idx];
+
+    if (!grub_strcmp (keyname, kv->key))
+      break;
+  }
+
+  if (idx == entry->nkeyvals) {
+    if (last)
+      *last = -1;
+    return NULL;
+  }
+
+  if (last)
+    *last = idx;
+
+  return kv->val;
+}
+
+#define goto_return(x) ({ ret = (x); goto finish; })
+
+/* compare alpha and numeric segments of two versions */
+/* return 1: a is newer than b */
+/*        0: a and b are the same version */
+/*       -1: b is newer than a */
+static int vercmp(const char * a, const char * b)
+{
+    char oldch1, oldch2;
+    char *abuf, *bbuf;
+    char *str1, *str2;
+    char * one, * two;
+    int rc;
+    int isnum;
+    int ret = 0;
+
+    grub_dprintf("blscfg", "%s comparing %s and %s\n", __func__, a, b);
+    if (!grub_strcmp(a, b))
+           return 0;
+
+    abuf = grub_malloc(grub_strlen(a) + 1);
+    bbuf = grub_malloc(grub_strlen(b) + 1);
+    str1 = abuf;
+    str2 = bbuf;
+    grub_strcpy(str1, a);
+    grub_strcpy(str2, b);
+
+    one = str1;
+    two = str2;
+
+    /* loop through each version segment of str1 and str2 and compare them */
+    while (*one || *two) {
+       while (*one && !grub_isalnum(*one) && *one != '~') one++;
+       while (*two && !grub_isalnum(*two) && *two != '~') two++;
+
+       /* handle the tilde separator, it sorts before everything else */
+       if (*one == '~' || *two == '~') {
+           if (*one != '~') goto_return (1);
+           if (*two != '~') goto_return (-1);
+           one++;
+           two++;
+           continue;
+       }
+
+       /* If we ran to the end of either, we are finished with the loop */
+       if (!(*one && *two)) break;
+
+       str1 = one;
+       str2 = two;
+
+       /* grab first completely alpha or completely numeric segment */
+       /* leave one and two pointing to the start of the alpha or numeric */
+       /* segment and walk str1 and str2 to end of segment */
+       if (grub_isdigit(*str1)) {
+           while (*str1 && grub_isdigit(*str1)) str1++;
+           while (*str2 && grub_isdigit(*str2)) str2++;
+           isnum = 1;
+       } else {
+           while (*str1 && grub_isalpha(*str1)) str1++;
+           while (*str2 && grub_isalpha(*str2)) str2++;
+           isnum = 0;
+       }
+
+       /* save character at the end of the alpha or numeric segment */
+       /* so that they can be restored after the comparison */
+       oldch1 = *str1;
+       *str1 = '\0';
+       oldch2 = *str2;
+       *str2 = '\0';
+
+       /* this cannot happen, as we previously tested to make sure that */
+       /* the first string has a non-null segment */
+       if (one == str1) goto_return(-1);       /* arbitrary */
+
+       /* take care of the case where the two version segments are */
+       /* different types: one numeric, the other alpha (i.e. empty) */
+       /* numeric segments are always newer than alpha segments */
+       /* XXX See patch #60884 (and details) from bugzilla #50977. */
+       if (two == str2) goto_return (isnum ? 1 : -1);
+
+       if (isnum) {
+           grub_size_t onelen, twolen;
+           /* this used to be done by converting the digit segments */
+           /* to ints using atoi() - it's changed because long  */
+           /* digit segments can overflow an int - this should fix that. */
+
+           /* throw away any leading zeros - it's a number, right? */
+           while (*one == '0') one++;
+           while (*two == '0') two++;
+
+           /* whichever number has more digits wins */
+           onelen = grub_strlen(one);
+           twolen = grub_strlen(two);
+           if (onelen > twolen) goto_return (1);
+           if (twolen > onelen) goto_return (-1);
+       }
+
+       /* grub_strcmp will return which one is greater - even if the two */
+       /* segments are alpha or if they are numeric.  don't return  */
+       /* if they are equal because there might be more segments to */
+       /* compare */
+       rc = grub_strcmp(one, two);
+       if (rc) goto_return (rc < 1 ? -1 : 1);
+
+       /* restore character that was replaced by null above */
+       *str1 = oldch1;
+       one = str1;
+       *str2 = oldch2;
+       two = str2;
+    }
+
+    /* this catches the case where all numeric and alpha segments have */
+    /* compared identically but the segment sepparating characters were */
+    /* different */
+    if ((!*one) && (!*two)) goto_return (0);
+
+    /* whichever version still has characters left over wins */
+    if (!*one) goto_return (-1); else goto_return (1);
+
+finish:
+    grub_free (abuf);
+    grub_free (bbuf);
+    return ret;
+}
+
+/* returns name/version/release */
+/* NULL string pointer returned if nothing found */
+static void
+split_package_string (char *package_string, char **name,
+                     char **version, char **release)
+{
+  char *package_version, *package_release;
+
+  /* Release */
+  package_release = grub_strrchr (package_string, '-');
+
+  if (package_release != NULL)
+      *package_release++ = '\0';
+
+  *release = package_release;
+
+  if (name == NULL)
+    {
+      *version = package_string;
+    }
+  else
+    {
+      /* Version */
+      package_version = grub_strrchr(package_string, '-');
+
+      if (package_version != NULL)
+       *package_version++ = '\0';
+
+      *version = package_version;
+      /* Name */
+      *name = package_string;
+    }
+
+  /* Bubble up non-null values from release to name */
+  if (name != NULL && *name == NULL)
+    {
+      *name = (*version == NULL ? *release : *version);
+      *version = *release;
+      *release = NULL;
+    }
+  if (*version == NULL)
+    {
+      *version = *release;
+      *release = NULL;
+    }
+}
+
+static int
+split_cmp(char *nvr0, char *nvr1, int has_name)
+{
+  int ret = 0;
+  char *name0, *version0, *release0;
+  char *name1, *version1, *release1;
+
+  split_package_string(nvr0, has_name ? &name0 : NULL, &version0, &release0);
+  split_package_string(nvr1, has_name ? &name1 : NULL, &version1, &release1);
+
+  if (has_name)
+    {
+      ret = vercmp(name0 == NULL ? "" : name0,
+                  name1 == NULL ? "" : name1);
+      if (ret != 0)
+       return ret;
+    }
+
+  ret = vercmp(version0 == NULL ? "" : version0,
+              version1 == NULL ? "" : version1);
+  if (ret != 0)
+    return ret;
+
+  ret = vercmp(release0 == NULL ? "" : release0,
+              release1 == NULL ? "" : release1);
+  return ret;
+}
+
+/* return 1: e0 is newer than e1 */
+/*        0: e0 and e1 are the same version */
+/*       -1: e1 is newer than e0 */
+static int bls_cmp(const struct bls_entry *e0, const struct bls_entry *e1)
+{
+  char *id0, *id1;
+  int r;
+
+  id0 = grub_strdup(e0->filename);
+  id1 = grub_strdup(e1->filename);
+
+  r = split_cmp(id0, id1, 1);
+
+  grub_free(id0);
+  grub_free(id1);
+
+  return r;
+}
+
+static void list_add_tail(struct bls_entry *head, struct bls_entry *item)
+{
+  item->next = head;
+  if (head->prev)
+    head->prev->next = item;
+  item->prev = head->prev;
+  head->prev = item;
+}
+
+static int bls_add_entry(struct bls_entry *entry)
+{
+  struct bls_entry *e, *last = NULL;
+  int rc;
+
+  if (!entries) {
+    grub_dprintf ("blscfg", "Add entry with id \"%s\"\n", entry->filename);
+    entries = entry;
+    return 0;
+  }
+
+  FOR_BLS_ENTRIES(e) {
+    rc = bls_cmp(entry, e);
+
+    if (!rc)
+      return GRUB_ERR_BAD_ARGUMENT;
+
+    if (rc == 1) {
+      grub_dprintf ("blscfg", "Add entry with id \"%s\"\n", entry->filename);
+      list_add_tail (e, entry);
+      if (e == entries) {
+       entries = entry;
+       entry->prev = NULL;
+      }
+      return 0;
+    }
+    last = e;
+  }
+
+  if (last) {
+    grub_dprintf ("blscfg", "Add entry with id \"%s\"\n", entry->filename);
+    last->next = entry;
+    entry->prev = last;
+  }
+
+  return 0;
+}
+
+struct read_entry_info {
+  const char *devid;
+  const char *dirname;
+  grub_file_t file;
+};
+
+static int read_entry (
+    const char *filename,
+    const struct grub_dirhook_info *dirhook_info UNUSED,
+    void *data)
+{
+  grub_size_t m = 0, n, clip = 0;
+  int rc = 0;
+  char *p = NULL;
+  grub_file_t f = NULL;
+  struct bls_entry *entry;
+  struct read_entry_info *info = (struct read_entry_info *)data;
+
+  grub_dprintf ("blscfg", "filename: \"%s\"\n", filename);
+
+  n = grub_strlen (filename);
+
+  if (info->file)
+    {
+      f = info->file;
+    }
+  else
+    {
+      if (filename[0] == '.')
+       return 0;
+
+      if (n <= 5)
+       return 0;
+
+      if (grub_strcmp (filename + n - 5, ".conf") != 0)
+       return 0;
+
+      p = grub_xasprintf ("(%s)%s/%s", info->devid, info->dirname, filename);
+
+      f = grub_file_open (p, GRUB_FILE_TYPE_CONFIG);
+      if (!f)
+       goto finish;
+    }
+
+  entry = grub_zalloc (sizeof (*entry));
+  if (!entry)
+    goto finish;
+
+  if (info->file)
+    {
+      char *slash;
+
+      if (n > 5 && !grub_strcmp (filename + n - 5, ".conf") == 0)
+       clip = 5;
+
+      slash = grub_strrchr (filename, '/');
+      if (!slash)
+       slash = grub_strrchr (filename, '\\');
+
+      while (*slash == '/' || *slash == '\\')
+       slash++;
+
+      m = slash ? slash - filename : 0;
+    }
+  else
+    {
+      m = 0;
+      clip = 5;
+    }
+  n -= m;
+
+  entry->filename = grub_strndup(filename + m, n - clip);
+  if (!entry->filename)
+    goto finish;
+
+  entry->filename[n - 5] = '\0';
+
+  for (;;)
+    {
+      char *buf;
+      char *separator;
+
+      buf = grub_file_getline (f);
+      if (!buf)
+       break;
+
+      while (buf && buf[0] && (buf[0] == ' ' || buf[0] == '\t'))
+       buf++;
+      if (buf[0] == '#')
+       continue;
+
+      separator = grub_strchr (buf, ' ');
+
+      if (!separator)
+       separator = grub_strchr (buf, '\t');
+
+      if (!separator || separator[1] == '\0')
+       {
+         grub_free (buf);
+         break;
+       }
+
+      separator[0] = '\0';
+
+      do {
+       separator++;
+      } while (*separator == ' ' || *separator == '\t');
+
+      rc = bls_add_keyval (entry, buf, separator);
+      grub_free (buf);
+      if (rc < 0)
+       break;
+    }
+
+    if (!rc)
+      bls_add_entry(entry);
+
+finish:
+  if (p)
+    grub_free (p);
+
+  if (f)
+    grub_file_close (f);
+
+  return 0;
+}
+
+static grub_envblk_t saved_env = NULL;
+
+static int UNUSED
+save_var (const char *name, const char *value, void *whitelist UNUSED)
+{
+  const char *val = grub_env_get (name);
+  grub_dprintf("blscfg", "saving \"%s\"\n", name);
+
+  if (val)
+    grub_envblk_set (saved_env, name, value);
+
+  return 0;
+}
+
+static int UNUSED
+unset_var (const char *name, const char *value UNUSED, void *whitelist)
+{
+  grub_dprintf("blscfg", "restoring \"%s\"\n", name);
+  if (! whitelist)
+    {
+      grub_env_unset (name);
+      return 0;
+    }
+
+  if (test_whitelist_membership (name,
+                                (const grub_env_whitelist_t *) whitelist))
+    grub_env_unset (name);
+
+  return 0;
+}
+
+static char **bls_make_list (struct bls_entry *entry, const char *key, int *num)
+{
+  int last = -1;
+  char *val;
+
+  int nlist = 0;
+  char **list = NULL;
+
+  list = grub_malloc (sizeof (char *));
+  if (!list)
+    return NULL;
+  list[0] = NULL;
+
+  while (1)
+    {
+      char **new;
+
+      val = bls_get_val (entry, key, &last);
+      if (!val)
+       break;
+
+      new = grub_realloc (list, (nlist + 2) * sizeof (char *));
+      if (!new)
+       break;
+
+      list = new;
+      list[nlist++] = val;
+      list[nlist] = NULL;
+  }
+
+  if (num)
+    *num = nlist;
+
+  return list;
+}
+
+static char *field_append(bool is_var, char *buffer, char *start, char *end)
+{
+  char *temp = grub_strndup(start, end - start + 1);
+  const char *field = temp;
+
+  if (is_var) {
+    field = grub_env_get (temp);
+    if (!field)
+      return buffer;
+  }
+
+  if (!buffer) {
+    buffer = grub_strdup(field);
+    if (!buffer)
+      return NULL;
+  } else {
+    buffer = grub_realloc (buffer, grub_strlen(buffer) + grub_strlen(field));
+    if (!buffer)
+      return NULL;
+
+    grub_stpcpy (buffer + grub_strlen(buffer), field);
+  }
+
+  return buffer;
+}
+
+static char *expand_val(char *value)
+{
+  char *buffer = NULL;
+  char *start = value;
+  char *end = value;
+  bool is_var = false;
+
+  if (!value)
+    return NULL;
+
+  while (*value) {
+    if (*value == '$') {
+      if (start != end) {
+       buffer = field_append(is_var, buffer, start, end);
+       if (!buffer)
+         return NULL;
+      }
+
+      is_var = true;
+      start = value + 1;
+    } else if (is_var) {
+      if (!grub_isalnum(*value) && *value != '_') {
+       buffer = field_append(is_var, buffer, start, end);
+       is_var = false;
+       start = value;
+      }
+    }
+
+    end = value;
+    value++;
+  }
+
+  if (start != end) {
+    buffer = field_append(is_var, buffer, start, end);
+    if (!buffer)
+      return NULL;
+  }
+
+  return buffer;
+}
+
+static char **early_initrd_list (const char *initrd)
+{
+  int nlist = 0;
+  char **list = NULL;
+  char *separator;
+
+  while ((separator = grub_strchr (initrd, ' ')))
+    {
+      list = grub_realloc (list, (nlist + 2) * sizeof (char *));
+      if (!list)
+        return NULL;
+
+      list[nlist++] = grub_strndup(initrd, separator - initrd);
+      list[nlist] = NULL;
+      initrd = separator + 1;
+  }
+
+  list = grub_realloc (list, (nlist + 2) * sizeof (char *));
+  if (!list)
+    return NULL;
+
+  list[nlist++] = grub_strndup(initrd, grub_strlen(initrd));
+  list[nlist] = NULL;
+
+  return list;
+}
+
+static void create_entry (struct bls_entry *entry)
+{
+  int argc = 0;
+  const char **argv = NULL;
+
+  char *title = NULL;
+  char *clinux = NULL;
+  char *options = NULL;
+  char **initrds = NULL;
+  char *initrd = NULL;
+  const char *early_initrd = NULL;
+  char **early_initrds = NULL;
+  char *initrd_prefix = NULL;
+  char *id = entry->filename;
+  char *dotconf = id;
+  char *hotkey = NULL;
+
+  char *users = NULL;
+  char **classes = NULL;
+
+  char **args = NULL;
+
+  char *src = NULL;
+  int bootlen;
+  const char *bootdev;
+  int i, index;
+
+  grub_dprintf("blscfg", "%s got here\n", __func__);
+  clinux = bls_get_val (entry, "linux", NULL);
+  if (!clinux)
+    {
+      grub_dprintf ("blscfg", "Skipping file %s with no 'linux' key.\n", entry->filename);
+      goto finish;
+    }
+
+  bootdev = grub_env_get("ventoy_bls_bootdev");
+  if (!bootdev)
+  {
+      bootdev = GRUB_BOOT_DEVICE;
+  }
+  bootlen = grub_strlen(bootdev) + 2;//space and \0
+
+  /*
+   * strip the ".conf" off the end before we make it our "id" field.
+   */
+  do
+    {
+      dotconf = grub_strstr(dotconf, ".conf");
+    } while (dotconf != NULL && dotconf[5] != '\0');
+  if (dotconf)
+    dotconf[0] = '\0';
+
+  title = bls_get_val (entry, "title", NULL);
+  options = expand_val (bls_get_val (entry, "options", NULL));
+
+  if (!options)
+    options = expand_val ((char *)grub_env_get("default_kernelopts"));
+
+  initrds = bls_make_list (entry, "initrd", NULL);
+
+  hotkey = bls_get_val (entry, "grub_hotkey", NULL);
+  users = expand_val (bls_get_val (entry, "grub_users", NULL));
+  classes = bls_make_list (entry, "grub_class", NULL);
+  args = bls_make_list (entry, "grub_arg", &argc);
+
+  argc += 1;
+  argv = grub_malloc ((argc + 1) * sizeof (char *));
+  argv[0] = title ? title : clinux;
+  for (i = 1; i < argc; i++)
+    argv[i] = args[i-1];
+  argv[argc] = NULL;
+
+  early_initrd = grub_env_get("early_initrd");
+
+  grub_dprintf ("blscfg", "adding menu entry for \"%s\" with id \"%s\"\n",
+               title, id);
+  if (early_initrd)
+    {
+      early_initrds = early_initrd_list(early_initrd);
+      if (!early_initrds)
+      {
+       grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+       goto finish;
+      }
+
+      if (initrds != NULL && initrds[0] != NULL)
+       {
+         initrd_prefix = grub_strrchr (initrds[0], '/');
+         initrd_prefix = grub_strndup(initrds[0], initrd_prefix - initrds[0] + 1);
+       }
+      else
+       {
+         initrd_prefix = grub_strrchr (clinux, '/');
+         initrd_prefix = grub_strndup(clinux, initrd_prefix - clinux + 1);
+       }
+
+      if (!initrd_prefix)
+       {
+         grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+         goto finish;
+       }
+    }
+
+  if (early_initrds || initrds)
+    {
+      int initrd_size = sizeof ("initrd");
+      char *tmp;
+
+      for (i = 0; early_initrds != NULL && early_initrds[i] != NULL; i++)
+       initrd_size += bootlen \
+                      + grub_strlen(initrd_prefix)  \
+                      + grub_strlen (early_initrds[i]) + 1;
+
+      for (i = 0; initrds != NULL && initrds[i] != NULL; i++)
+       initrd_size += bootlen \
+                      + grub_strlen (initrds[i]) + 1;
+      initrd_size += 1;
+
+      initrd = grub_malloc (initrd_size);
+      if (!initrd)
+       {
+         grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+         goto finish;
+       }
+
+
+      tmp = grub_stpcpy(initrd, "initrd");
+      for (i = 0; early_initrds != NULL && early_initrds[i] != NULL; i++)
+       {
+         grub_dprintf ("blscfg", "adding early initrd %s\n", early_initrds[i]);
+         tmp = grub_stpcpy (tmp, " ");
+         tmp = grub_stpcpy (tmp, bootdev);
+         tmp = grub_stpcpy (tmp, initrd_prefix);
+         tmp = grub_stpcpy (tmp, early_initrds[i]);
+         grub_free(early_initrds[i]);
+       }
+
+      for (i = 0; initrds != NULL && initrds[i] != NULL; i++)
+       {
+         grub_dprintf ("blscfg", "adding initrd %s\n", initrds[i]);
+         tmp = grub_stpcpy (tmp, " ");
+         tmp = grub_stpcpy (tmp, bootdev);
+         tmp = grub_stpcpy (tmp, initrds[i]);
+       }
+      tmp = grub_stpcpy (tmp, "\n");
+    }
+
+  src = grub_xasprintf ("load_video\n"
+                       "set gfxpayload=keep\n"
+                       "insmod gzio\n"
+                       "linux %s%s%s%s\n"
+                       "%s",
+                       bootdev, clinux, options ? " " : "", options ? options : "",
+                       initrd ? initrd : "");
+
+  grub_normal_add_menu_entry (argc, argv, classes, id, users, hotkey, NULL, src, 0, &index, entry);
+  grub_dprintf ("blscfg", "Added entry %d id:\"%s\"\n", index, id);
+
+finish:
+  grub_free (initrd);
+  grub_free (initrd_prefix);
+  grub_free (early_initrds);
+  grub_free (initrds);
+  grub_free (options);
+  grub_free (classes);
+  grub_free (args);
+  grub_free (argv);
+  grub_free (src);
+}
+
+struct find_entry_info {
+       const char *dirname;
+       const char *devid;
+       grub_device_t dev;
+       grub_fs_t fs;
+};
+
+/*
+ * info: the filesystem object the file is on.
+ */
+static int find_entry (struct find_entry_info *info)
+{
+  struct read_entry_info read_entry_info;
+  grub_fs_t blsdir_fs = NULL;
+  grub_device_t blsdir_dev = NULL;
+  const char *blsdir = info->dirname;
+  int fallback = 0;
+  int r = 0;
+
+  if (!blsdir) {
+    blsdir = grub_env_get ("blsdir");
+    if (!blsdir)
+      blsdir = GRUB_BLS_CONFIG_PATH;
+  }
+
+  read_entry_info.file = NULL;
+  read_entry_info.dirname = blsdir;
+
+  grub_dprintf ("blscfg", "scanning blsdir: %s\n", blsdir);
+
+  blsdir_dev = info->dev;
+  blsdir_fs = info->fs;
+  read_entry_info.devid = info->devid;
+
+read_fallback:
+  r = blsdir_fs->fs_dir (blsdir_dev, read_entry_info.dirname, read_entry,
+                        &read_entry_info);
+  if (r != 0) {
+      grub_dprintf ("blscfg", "read_entry returned error\n");
+      grub_err_t e;
+      do
+       {
+         e = grub_error_pop();
+       } while (e);
+  }
+
+  if (r && !info->dirname && !fallback) {
+    read_entry_info.dirname = "/boot" GRUB_BLS_CONFIG_PATH;
+    grub_dprintf ("blscfg", "Entries weren't found in %s, fallback to %s\n",
+                 blsdir, read_entry_info.dirname);
+    fallback = 1;
+    goto read_fallback;
+  }
+
+  return 0;
+}
+
+static grub_err_t
+bls_load_entries (const char *path)
+{
+  grub_size_t len;
+  grub_fs_t fs;
+  grub_device_t dev;
+  static grub_err_t r;
+  const char *devid = NULL;
+  char *blsdir = NULL;
+  struct find_entry_info info = {
+      .dev = NULL,
+      .fs = NULL,
+      .dirname = NULL,
+  };
+  struct read_entry_info rei = {
+      .devid = NULL,
+      .dirname = NULL,
+  };
+
+  if (path) {
+    len = grub_strlen (path);
+    if (grub_strcmp (path + len - 5, ".conf") == 0) {
+      rei.file = grub_file_open (path, GRUB_FILE_TYPE_CONFIG);
+      if (!rei.file)
+       return grub_errno;
+      /*
+       * read_entry() closes the file
+       */
+      return read_entry(path, NULL, &rei);
+    } else if (path[0] == '(') {
+      devid = path + 1;
+
+      blsdir = grub_strchr (path, ')');
+      if (!blsdir)
+       return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Filepath isn't correct"));
+
+      *blsdir = '\0';
+      blsdir = blsdir + 1;
+    }
+  }
+
+  if (!devid) {
+#ifdef GRUB_MACHINE_EMU
+    devid = "host";
+#elif defined(GRUB_MACHINE_EFI)
+    devid = grub_env_get ("root");
+#else
+    devid = grub_env_get ("boot");
+    if (!devid)
+    {
+        devid = grub_env_get ("root");
+    }
+#endif
+    if (!devid)
+      return grub_error (GRUB_ERR_FILE_NOT_FOUND,
+                        N_("variable `%s' isn't set"), "boot");
+  }
+
+  grub_dprintf ("blscfg", "opening %s\n", devid);
+  dev = grub_device_open (devid);
+  if (!dev)
+    return grub_errno;
+
+  grub_dprintf ("blscfg", "probing fs\n");
+  fs = grub_fs_probe (dev);
+  if (!fs)
+    {
+      r = grub_errno;
+      goto finish;
+    }
+
+  info.dirname = blsdir;
+  info.devid = devid;
+  info.dev = dev;
+  info.fs = fs;
+  find_entry(&info);
+
+finish:
+  if (dev)
+    grub_device_close (dev);
+
+  return r;
+}
+
+static bool
+is_default_entry(const char *def_entry, struct bls_entry *entry, int idx)
+{
+  const char *title;
+  int def_idx;
+
+  if (!def_entry)
+    return false;
+
+  if (grub_strcmp(def_entry, entry->filename) == 0)
+    return true;
+
+  title = bls_get_val(entry, "title", NULL);
+
+  if (title && grub_strcmp(def_entry, title) == 0)
+    return true;
+
+  def_idx = (int)grub_strtol(def_entry, NULL, 0);
+  if (grub_errno == GRUB_ERR_BAD_NUMBER) {
+    grub_errno = GRUB_ERR_NONE;
+    return false;
+  }
+
+  if (def_idx == idx)
+    return true;
+
+  return false;
+}
+
+static grub_err_t
+bls_create_entries (bool show_default, bool show_non_default, char *entry_id)
+{
+  const char *def_entry = NULL;
+  struct bls_entry *entry = NULL;
+  int idx = 0;
+
+  def_entry = grub_env_get("default");
+
+  grub_dprintf ("blscfg", "%s Creating entries from bls\n", __func__);
+  FOR_BLS_ENTRIES(entry) {
+    if (entry->visible) {
+      idx++;
+      continue;
+    }
+
+    if ((show_default && is_default_entry(def_entry, entry, idx)) ||
+       (show_non_default && !is_default_entry(def_entry, entry, idx)) ||
+       (entry_id && grub_strcmp(entry_id, entry->filename) == 0)) {
+      create_entry(entry);
+      entry->visible = 1;
+    }
+    idx++;
+  }
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_cmd_blscfg (grub_extcmd_context_t ctxt UNUSED,
+                int argc, char **args)
+{
+  grub_err_t r;
+  char *path = NULL;
+  char *entry_id = NULL;
+  bool show_default = true;
+  bool show_non_default = true;
+
+  if (argc == 1) {
+    if (grub_strcmp (args[0], "default") == 0) {
+      show_non_default = false;
+    } else if (grub_strcmp (args[0], "non-default") == 0) {
+      show_default = false;
+    } else if (args[0][0] == '(') {
+      path = args[0];
+    } else {
+      entry_id = args[0];
+      show_default = false;
+      show_non_default = false;
+    }
+  }
+
+  r = bls_load_entries(path);
+  if (r)
+    return r;
+
+  return bls_create_entries(show_default, show_non_default, entry_id);
+}
+
+static grub_extcmd_t cmd;
+static grub_extcmd_t oldcmd;
+
+GRUB_MOD_INIT(blscfg)
+{
+  grub_dprintf("blscfg", "%s got here\n", __func__);
+  cmd = grub_register_extcmd ("blscfg",
+                             grub_cmd_blscfg,
+                             0,
+                             NULL,
+                             N_("Import Boot Loader Specification snippets."),
+                             NULL);
+  oldcmd = grub_register_extcmd ("bls_import",
+                                grub_cmd_blscfg,
+                                0,
+                                NULL,
+                                N_("Import Boot Loader Specification snippets."),
+                                NULL);
+}
+
+GRUB_MOD_FINI(blscfg)
+{
+  grub_unregister_extcmd (cmd);
+  grub_unregister_extcmd (oldcmd);
+}
diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/commands/legacycfg.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/commands/legacycfg.c
new file mode 100644 (file)
index 0000000..891eac5
--- /dev/null
@@ -0,0 +1,894 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2000, 2001, 2010  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/types.h>
+#include <grub/misc.h>
+#include <grub/command.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/file.h>
+#include <grub/normal.h>
+#include <grub/script_sh.h>
+#include <grub/i18n.h>
+#include <grub/term.h>
+#include <grub/legacy_parse.h>
+#include <grub/crypto.h>
+#include <grub/auth.h>
+#include <grub/disk.h>
+#include <grub/partition.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+/* Helper for legacy_file.  */
+static grub_err_t
+legacy_file_getline (char **line, int cont __attribute__ ((unused)),
+                    void *data __attribute__ ((unused)))
+{
+  *line = 0;
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+legacy_file (const char *filename)
+{
+  grub_file_t file;
+  char *entryname = NULL, *entrysrc = NULL;
+  grub_menu_t menu;
+  char *suffix = grub_strdup ("");
+
+  if (!suffix)
+    return grub_errno;
+
+  file = grub_file_open (filename, GRUB_FILE_TYPE_CONFIG);
+  if (! file)
+    {
+      grub_free (suffix);
+      return grub_errno;
+    }
+
+  menu = grub_env_get_menu ();
+  if (! menu)
+    {
+      menu = grub_zalloc (sizeof (*menu));
+      if (! menu)
+       {
+         grub_free (suffix);
+         return grub_errno;
+       }
+
+      grub_env_set_menu (menu);
+    }
+
+  while (1)
+    {
+      char *buf = grub_file_getline (file);
+      char *parsed = NULL;
+
+      if (!buf && grub_errno)
+       {
+         grub_file_close (file);
+         grub_free (suffix);
+         return grub_errno;
+       }
+
+      if (!buf)
+       break;
+
+      {
+       char *oldname = NULL;
+       char *newsuffix;
+       char *ptr;
+
+       for (ptr = buf; *ptr && grub_isspace (*ptr); ptr++);
+
+       oldname = entryname;
+       parsed = grub_legacy_parse (ptr, &entryname, &newsuffix);
+       grub_free (buf);
+       buf = NULL;
+       if (newsuffix)
+         {
+           char *t;
+           
+           t = suffix;
+           suffix = grub_realloc (suffix, grub_strlen (suffix)
+                                  + grub_strlen (newsuffix) + 1);
+           if (!suffix)
+             {
+               grub_free (t);
+               grub_free (entrysrc);
+               grub_free (parsed);
+               grub_free (newsuffix);
+               grub_free (suffix);
+               return grub_errno;
+             }
+           grub_memcpy (suffix + grub_strlen (suffix), newsuffix,
+                        grub_strlen (newsuffix) + 1);
+           grub_free (newsuffix);
+           newsuffix = NULL;
+         }
+       if (oldname != entryname && oldname)
+         {
+           const char **args = grub_malloc (sizeof (args[0]));
+           if (!args)
+             {
+               grub_file_close (file);
+               return grub_errno;
+             }
+           args[0] = oldname;
+           grub_normal_add_menu_entry (1, args, NULL, NULL, "legacy",
+                                       NULL, NULL,
+                                       entrysrc, 0, NULL, NULL);
+           grub_free (args);
+           entrysrc[0] = 0;
+           grub_free (oldname);
+         }
+      }
+
+      if (parsed && !entryname)
+       {
+         grub_normal_parse_line (parsed, legacy_file_getline, NULL);
+         grub_print_error ();
+         grub_free (parsed);
+         parsed = NULL;
+       }
+      else if (parsed)
+       {
+         if (!entrysrc)
+           entrysrc = parsed;
+         else
+           {
+             char *t;
+
+             t = entrysrc;
+             entrysrc = grub_realloc (entrysrc, grub_strlen (entrysrc)
+                                      + grub_strlen (parsed) + 1);
+             if (!entrysrc)
+               {
+                 grub_free (t);
+                 grub_free (parsed);
+                 grub_free (suffix);
+                 return grub_errno;
+               }
+             grub_memcpy (entrysrc + grub_strlen (entrysrc), parsed,
+                          grub_strlen (parsed) + 1);
+             grub_free (parsed);
+             parsed = NULL;
+           }
+       }
+    }
+  grub_file_close (file);
+
+  if (entryname)
+    {
+      const char **args = grub_malloc (sizeof (args[0]));
+      if (!args)
+       {
+         grub_file_close (file);
+         grub_free (suffix);
+         grub_free (entrysrc);
+         return grub_errno;
+       }
+      args[0] = entryname;
+      grub_normal_add_menu_entry (1, args, NULL, NULL, NULL,
+                                 NULL, NULL, entrysrc, 0, NULL,
+                                 NULL);
+      grub_free (args);
+    }
+
+  grub_normal_parse_line (suffix, legacy_file_getline, NULL);
+  grub_print_error ();
+  grub_free (suffix);
+  grub_free (entrysrc);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_cmd_legacy_source (struct grub_command *cmd,
+                       int argc, char **args)
+{
+  int new_env, extractor;
+  grub_err_t ret;
+
+  if (argc != 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+
+  extractor = (cmd->name[0] == 'e');
+  new_env = (cmd->name[extractor ? (sizeof ("extract_legacy_entries_") - 1)
+                      : (sizeof ("legacy_") - 1)] == 'c');
+
+  if (new_env)
+    grub_cls ();
+
+  if (new_env && !extractor)
+    grub_env_context_open ();
+  if (extractor)
+    grub_env_extractor_open (!new_env);
+
+  ret = legacy_file (args[0]);
+
+  if (new_env)
+    {
+      grub_menu_t menu;
+      menu = grub_env_get_menu ();
+      if (menu && menu->size)
+       grub_show_menu (menu, 1, 0);
+      if (!extractor)
+       grub_env_context_close ();
+    }
+  if (extractor)
+    grub_env_extractor_close (!new_env);
+
+  return ret;
+}
+
+static enum
+  { 
+    GUESS_IT, LINUX, MULTIBOOT, KFREEBSD, KNETBSD, KOPENBSD 
+  } kernel_type;
+
+static grub_err_t
+grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
+                       int argc, char **args)
+{
+  int i;
+#ifdef TODO
+  int no_mem_option = 0;
+#endif
+  struct grub_command *cmd;
+  char **cutargs;
+  int cutargc;
+  grub_err_t err = GRUB_ERR_NONE;
+  
+  for (i = 0; i < 2; i++)
+    {
+      /* FIXME: really support this.  */
+      if (argc >= 1 && grub_strcmp (args[0], "--no-mem-option") == 0)
+       {
+#ifdef TODO
+         no_mem_option = 1;
+#endif
+         argc--;
+         args++;
+         continue;
+       }
+
+      /* linux16 handles both zImages and bzImages.   */
+      if (argc >= 1 && (grub_strcmp (args[0], "--type=linux") == 0
+                       || grub_strcmp (args[0], "--type=biglinux") == 0))
+       {
+         kernel_type = LINUX;
+         argc--;
+         args++;
+         continue;
+       }
+
+      if (argc >= 1 && grub_strcmp (args[0], "--type=multiboot") == 0)
+       {
+         kernel_type = MULTIBOOT;
+         argc--;
+         args++;
+         continue;
+       }
+
+      if (argc >= 1 && grub_strcmp (args[0], "--type=freebsd") == 0)
+       {
+         kernel_type = KFREEBSD;
+         argc--;
+         args++;
+         continue;
+       }
+
+      if (argc >= 1 && grub_strcmp (args[0], "--type=openbsd") == 0)
+       {
+         kernel_type = KOPENBSD;
+         argc--;
+         args++;
+         continue;
+       }
+
+      if (argc >= 1 && grub_strcmp (args[0], "--type=netbsd") == 0)
+       {
+         kernel_type = KNETBSD;
+         argc--;
+         args++;
+         continue;
+       }
+    }
+
+  if (argc < 2)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+
+  cutargs = grub_malloc (sizeof (cutargs[0]) * (argc - 1));
+  if (!cutargs)
+    return grub_errno;
+  cutargc = argc - 1;
+  grub_memcpy (cutargs + 1, args + 2, sizeof (cutargs[0]) * (argc - 2));
+  cutargs[0] = args[0];
+
+  do
+    {
+      /* First try Linux.  */
+      if (kernel_type == GUESS_IT || kernel_type == LINUX)
+       {
+#ifdef GRUB_MACHINE_PCBIOS
+         cmd = grub_command_find ("linux16");
+#else
+         cmd = grub_command_find ("linux");
+#endif
+         if (cmd)
+           {
+             if (!(cmd->func) (cmd, cutargc, cutargs))
+               {
+                 kernel_type = LINUX;
+                 goto out;
+               }
+           }
+         grub_errno = GRUB_ERR_NONE;
+       }
+
+      /* Then multiboot.  */
+      if (kernel_type == GUESS_IT || kernel_type == MULTIBOOT)
+       {
+         cmd = grub_command_find ("multiboot");
+         if (cmd)
+           {
+             if (!(cmd->func) (cmd, argc, args))
+               {
+                 kernel_type = MULTIBOOT;
+                 goto out;
+               }
+           }
+         grub_errno = GRUB_ERR_NONE;
+       }
+
+      {
+       int bsd_device = -1;
+       int bsd_slice = -1;
+       int bsd_part = -1;
+       {
+         grub_device_t dev;
+         const char *hdbiasstr;
+         int hdbias = 0;
+         hdbiasstr = grub_env_get ("legacy_hdbias");
+         if (hdbiasstr)
+           {
+             hdbias = grub_strtoul (hdbiasstr, 0, 0);
+             grub_errno = GRUB_ERR_NONE;
+           }
+         dev = grub_device_open (0);
+         if (dev && dev->disk
+             && dev->disk->dev->id == GRUB_DISK_DEVICE_BIOSDISK_ID
+             && dev->disk->id >= 0x80 && dev->disk->id <= 0x90)
+           {
+             struct grub_partition *part = dev->disk->partition;
+             bsd_device = dev->disk->id - 0x80 - hdbias;
+             if (part && (grub_strcmp (part->partmap->name, "netbsd") == 0
+                          || grub_strcmp (part->partmap->name, "openbsd") == 0
+                          || grub_strcmp (part->partmap->name, "bsd") == 0))
+               {
+                 bsd_part = part->number;
+                 part = part->parent;
+               }
+             if (part && grub_strcmp (part->partmap->name, "msdos") == 0)
+               bsd_slice = part->number;
+           }
+         if (dev)
+           grub_device_close (dev);
+       }
+       
+       /* k*BSD didn't really work well with grub-legacy.  */
+       if (kernel_type == GUESS_IT || kernel_type == KFREEBSD)
+         {
+           char buf[sizeof("adXXXXXXXXXXXXsXXXXXXXXXXXXYYY")];
+           if (bsd_device != -1)
+             {
+               if (bsd_slice != -1 && bsd_part != -1)
+                 grub_snprintf(buf, sizeof(buf), "ad%ds%d%c", bsd_device,
+                               bsd_slice, 'a' + bsd_part);
+               else if (bsd_slice != -1)
+                 grub_snprintf(buf, sizeof(buf), "ad%ds%d", bsd_device,
+                               bsd_slice);
+               else
+                 grub_snprintf(buf, sizeof(buf), "ad%d", bsd_device);
+               grub_env_set ("kFreeBSD.vfs.root.mountfrom", buf);
+             }
+           else
+             grub_env_unset ("kFreeBSD.vfs.root.mountfrom");
+           cmd = grub_command_find ("kfreebsd");
+           if (cmd)
+             {
+               if (!(cmd->func) (cmd, cutargc, cutargs))
+                 {
+                   kernel_type = KFREEBSD;
+                   goto out;
+                 }
+             }
+           grub_errno = GRUB_ERR_NONE;
+         }
+       {
+         char **bsdargs;
+         int bsdargc;
+         char bsddevname[sizeof ("wdXXXXXXXXXXXXY")];
+         int found = 0;
+
+         if (bsd_device == -1)
+           {
+             bsdargs = cutargs;
+             bsdargc = cutargc;
+           }
+         else
+           {
+             char rbuf[3] = "-r";
+             bsdargc = cutargc + 2;
+             bsdargs = grub_malloc (sizeof (bsdargs[0]) * bsdargc);
+             if (!bsdargs)
+               {
+                 err = grub_errno;
+                 goto out;
+               }
+             grub_memcpy (bsdargs, args, argc * sizeof (bsdargs[0]));
+             bsdargs[argc] = rbuf;
+             bsdargs[argc + 1] = bsddevname;
+             grub_snprintf (bsddevname, sizeof (bsddevname),
+                            "wd%d%c", bsd_device,
+                            bsd_part != -1 ? bsd_part + 'a' : 'c');
+           }
+         if (kernel_type == GUESS_IT || kernel_type == KNETBSD)
+           {
+             cmd = grub_command_find ("knetbsd");
+             if (cmd)
+               {
+                 if (!(cmd->func) (cmd, bsdargc, bsdargs))
+                   {
+                     kernel_type = KNETBSD;
+                     found = 1;
+                     goto free_bsdargs;
+                   }
+               }
+             grub_errno = GRUB_ERR_NONE;
+           }
+         if (kernel_type == GUESS_IT || kernel_type == KOPENBSD)
+           {
+             cmd = grub_command_find ("kopenbsd");
+             if (cmd)
+               {
+                 if (!(cmd->func) (cmd, bsdargc, bsdargs))
+                   {
+                     kernel_type = KOPENBSD;
+                     found = 1;
+                     goto free_bsdargs;
+                   }
+               }
+             grub_errno = GRUB_ERR_NONE;
+           }
+
+free_bsdargs:
+         if (bsdargs != cutargs)
+           grub_free (bsdargs);
+         if (found)
+           goto out;
+       }
+      }
+    }
+  while (0);
+
+  err = grub_error (GRUB_ERR_BAD_OS, "couldn't load file %s",
+                   args[0]);
+out:
+  grub_free (cutargs);
+  return err;
+}
+
+static grub_err_t
+grub_cmd_legacy_initrd (struct grub_command *mycmd __attribute__ ((unused)),
+                       int argc, char **args)
+{
+  struct grub_command *cmd;
+
+  if (kernel_type == LINUX)
+    {
+#ifdef GRUB_MACHINE_PCBIOS
+      cmd = grub_command_find ("initrd16");
+#else
+      cmd = grub_command_find ("initrd");
+#endif
+      if (!cmd)
+       return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"),
+#ifdef GRUB_MACHINE_PCBIOS
+                          "initrd16"
+#else
+                          "initrd"
+#endif
+                          );
+
+      return cmd->func (cmd, argc ? 1 : 0, args);
+    }
+  if (kernel_type == MULTIBOOT)
+    {
+      cmd = grub_command_find ("module");
+      if (!cmd)
+       return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"),
+                          "module");
+
+      return cmd->func (cmd, argc, args);
+    }
+
+  return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                    N_("you need to load the kernel first"));
+}
+
+static grub_err_t
+grub_cmd_legacy_initrdnounzip (struct grub_command *mycmd __attribute__ ((unused)),
+                              int argc, char **args)
+{
+  struct grub_command *cmd;
+
+  if (kernel_type == LINUX)
+    {
+      cmd = grub_command_find ("initrd16");
+      if (!cmd)
+       return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"),
+                          "initrd16");
+
+      return cmd->func (cmd, argc, args);
+    }
+  if (kernel_type == MULTIBOOT)
+    {
+      char **newargs;
+      grub_err_t err;
+      char nounzipbuf[10] = "--nounzip";
+
+      cmd = grub_command_find ("module");
+      if (!cmd)
+       return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"),
+                          "module");
+
+      newargs = grub_malloc ((argc + 1) * sizeof (newargs[0]));
+      if (!newargs)
+       return grub_errno;
+      grub_memcpy (newargs + 1, args, argc * sizeof (newargs[0]));
+      newargs[0] = nounzipbuf;
+
+      err = cmd->func (cmd, argc + 1, newargs);
+      grub_free (newargs);
+      return err;
+    }
+
+  return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                    N_("you need to load the kernel first"));
+}
+
+static grub_err_t
+check_password_deny (const char *user __attribute__ ((unused)),
+                    const char *entered  __attribute__ ((unused)),
+                    void *password __attribute__ ((unused)))
+{
+  return GRUB_ACCESS_DENIED;
+}
+
+#define MD5_HASHLEN 16
+
+struct legacy_md5_password
+{
+  grub_uint8_t *salt;
+  int saltlen;
+  grub_uint8_t hash[MD5_HASHLEN];
+};
+
+static int
+check_password_md5_real (const char *entered,
+                        struct legacy_md5_password *pw)
+{
+  grub_size_t enteredlen = grub_strlen (entered);
+  unsigned char alt_result[MD5_HASHLEN];
+  unsigned char *digest;
+  grub_uint8_t *ctx;
+  grub_size_t i;
+  int ret;
+
+  ctx = grub_zalloc (GRUB_MD_MD5->contextsize);
+  if (!ctx)
+    return 0;
+
+  GRUB_MD_MD5->init (ctx);
+  GRUB_MD_MD5->write (ctx, entered, enteredlen);
+  GRUB_MD_MD5->write (ctx, pw->salt + 3, pw->saltlen - 3);
+  GRUB_MD_MD5->write (ctx, entered, enteredlen);
+  digest = GRUB_MD_MD5->read (ctx);
+  GRUB_MD_MD5->final (ctx);
+  grub_memcpy (alt_result, digest, MD5_HASHLEN);
+  
+  GRUB_MD_MD5->init (ctx);
+  GRUB_MD_MD5->write (ctx, entered, enteredlen);
+  GRUB_MD_MD5->write (ctx, pw->salt, pw->saltlen); /* include the $1$ header */
+  for (i = enteredlen; i > 16; i -= 16)
+    GRUB_MD_MD5->write (ctx, alt_result, 16);
+  GRUB_MD_MD5->write (ctx, alt_result, i);
+
+  for (i = enteredlen; i > 0; i >>= 1)
+    GRUB_MD_MD5->write (ctx, entered + ((i & 1) ? enteredlen : 0), 1);
+  digest = GRUB_MD_MD5->read (ctx);
+  GRUB_MD_MD5->final (ctx);
+
+  for (i = 0; i < 1000; i++)
+    {
+      grub_memcpy (alt_result, digest, 16);
+
+      GRUB_MD_MD5->init (ctx);
+      if ((i & 1) != 0)
+       GRUB_MD_MD5->write (ctx, entered, enteredlen);
+      else
+       GRUB_MD_MD5->write (ctx, alt_result, 16);
+      
+      if (i % 3 != 0)
+       GRUB_MD_MD5->write (ctx, pw->salt + 3, pw->saltlen - 3);
+
+      if (i % 7 != 0)
+       GRUB_MD_MD5->write (ctx, entered, enteredlen);
+
+      if ((i & 1) != 0)
+       GRUB_MD_MD5->write (ctx, alt_result, 16);
+      else
+       GRUB_MD_MD5->write (ctx, entered, enteredlen);
+      digest = GRUB_MD_MD5->read (ctx);
+      GRUB_MD_MD5->final (ctx);
+    }
+
+  ret = (grub_crypto_memcmp (digest, pw->hash, MD5_HASHLEN) == 0);
+  grub_free (ctx);
+  return ret;
+}
+
+static grub_err_t
+check_password_md5 (const char *user,
+                   const char *entered,
+                   void *password)
+{
+  if (!check_password_md5_real (entered, password))
+    return GRUB_ACCESS_DENIED;
+
+  grub_auth_authenticate (user);
+
+  return GRUB_ERR_NONE;
+}
+
+static inline int
+ib64t (char c)
+{
+  if (c == '.')
+    return 0;
+  if (c == '/')
+    return 1;
+  if (c >= '0' && c <= '9')
+    return c - '0' + 2;
+  if (c >= 'A' && c <= 'Z')
+    return c - 'A' + 12;
+  if (c >= 'a' && c <= 'z')
+    return c - 'a' + 38;
+  return -1;
+}
+
+static struct legacy_md5_password *
+parse_legacy_md5 (int argc, char **args)
+{
+  const char *salt, *saltend;
+  struct legacy_md5_password *pw = NULL;
+  int i;
+  const char *p;
+
+  if (grub_memcmp (args[0], "--md5", sizeof ("--md5")) != 0)
+    goto fail;
+  if (argc == 1)
+    goto fail;
+  if (grub_strlen(args[1]) <= 3)
+    goto fail;
+  salt = args[1];
+  saltend = grub_strchr (salt + 3, '$');
+  if (!saltend)
+    goto fail;
+  pw = grub_malloc (sizeof (*pw));
+  if (!pw)
+    goto fail;
+
+  p = saltend + 1;
+  for (i = 0; i < 5; i++)
+    {
+      int n;
+      grub_uint32_t w = 0;
+
+      for (n = 0; n < 4; n++)
+       {
+         int ww = ib64t(*p++);
+         if (ww == -1)
+           goto fail;
+         w |= ww << (n * 6);
+       }
+      pw->hash[i == 4 ? 5 : 12+i] = w & 0xff;
+      pw->hash[6+i] = (w >> 8) & 0xff;
+      pw->hash[i] = (w >> 16) & 0xff;
+    }
+  {
+    int n;
+    grub_uint32_t w = 0;
+    for (n = 0; n < 2; n++)
+      {
+       int ww = ib64t(*p++);
+       if (ww == -1)
+         goto fail;
+       w |= ww << (6 * n);
+      }
+    if (w >= 0x100)
+      goto fail;
+    pw->hash[11] = w;
+  }
+
+  pw->saltlen = saltend - salt;
+  pw->salt = (grub_uint8_t *) grub_strndup (salt, pw->saltlen);
+  if (!pw->salt)
+    goto fail;
+
+  return pw;
+
+ fail:
+  grub_free (pw);
+  return NULL;
+}
+
+static grub_err_t
+grub_cmd_legacy_password (struct grub_command *mycmd __attribute__ ((unused)),
+                         int argc, char **args)
+{
+  struct legacy_md5_password *pw = NULL;
+
+  if (argc == 0)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
+  if (args[0][0] != '-' || args[0][1] != '-')
+    return grub_normal_set_password ("legacy", args[0]);
+
+  pw = parse_legacy_md5 (argc, args);
+
+  if (pw)
+    return grub_auth_register_authentication ("legacy", check_password_md5, pw);
+  else
+    /* This is to imitate minor difference between grub-legacy in GRUB2.
+       If 2 password commands are executed in a row and second one fails
+       on GRUB2 the password of first one is used, whereas in grub-legacy
+       authenthication is denied. In case of no password command was executed
+       early both versions deny any access.  */
+    return grub_auth_register_authentication ("legacy", check_password_deny,
+                                             NULL);
+}
+
+int
+grub_legacy_check_md5_password (int argc, char **args,
+                               char *entered)
+{
+  struct legacy_md5_password *pw = NULL;
+  int ret;
+
+  if (args[0][0] != '-' || args[0][1] != '-')
+    {
+      char correct[GRUB_AUTH_MAX_PASSLEN];
+
+      grub_memset (correct, 0, sizeof (correct));
+      grub_strncpy (correct, args[0], sizeof (correct));
+
+      return grub_crypto_memcmp (entered, correct, GRUB_AUTH_MAX_PASSLEN) == 0;
+    }
+
+  pw = parse_legacy_md5 (argc, args);
+
+  if (!pw)
+    return 0;
+
+  ret = check_password_md5_real (entered, pw);
+  grub_free (pw);
+  return ret;
+}
+
+static grub_err_t
+grub_cmd_legacy_check_password (struct grub_command *mycmd __attribute__ ((unused)),
+                               int argc, char **args)
+{
+  char entered[GRUB_AUTH_MAX_PASSLEN];
+
+  if (argc == 0)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
+  grub_puts_ (N_("Enter password: "));
+  if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN))
+    return GRUB_ACCESS_DENIED;
+
+  if (!grub_legacy_check_md5_password (argc, args,
+                                      entered))
+    return GRUB_ACCESS_DENIED;
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_command_t cmd_source, cmd_configfile;
+static grub_command_t cmd_source_extract, cmd_configfile_extract;
+static grub_command_t cmd_kernel, cmd_initrd, cmd_initrdnounzip;
+static grub_command_t cmd_password, cmd_check_password;
+
+GRUB_MOD_INIT(legacycfg)
+{
+  cmd_source
+    = grub_register_command ("legacy_source",
+                            grub_cmd_legacy_source,
+                            N_("FILE"),
+                            /* TRANSLATORS: "legacy config" means
+                               "config as used by grub-legacy".  */
+                            N_("Parse legacy config in same context"));
+  cmd_configfile
+    = grub_register_command ("legacy_configfile",
+                            grub_cmd_legacy_source,
+                            N_("FILE"),
+                            N_("Parse legacy config in new context"));
+  cmd_source_extract
+    = grub_register_command ("extract_legacy_entries_source",
+                            grub_cmd_legacy_source,
+                            N_("FILE"),
+                            N_("Parse legacy config in same context taking only menu entries"));
+  cmd_configfile_extract
+    = grub_register_command ("extract_legacy_entries_configfile",
+                            grub_cmd_legacy_source,
+                            N_("FILE"),
+                            N_("Parse legacy config in new context taking only menu entries"));
+
+  cmd_kernel = grub_register_command ("legacy_kernel",
+                                     grub_cmd_legacy_kernel,
+                                     N_("[--no-mem-option] [--type=TYPE] FILE [ARG ...]"),
+                                     N_("Simulate grub-legacy `kernel' command"));
+
+  cmd_initrd = grub_register_command ("legacy_initrd",
+                                     grub_cmd_legacy_initrd,
+                                     N_("FILE [ARG ...]"),
+                                     N_("Simulate grub-legacy `initrd' command"));
+  cmd_initrdnounzip = grub_register_command ("legacy_initrd_nounzip",
+                                            grub_cmd_legacy_initrdnounzip,
+                                            N_("FILE [ARG ...]"),
+                                            N_("Simulate grub-legacy `modulenounzip' command"));
+
+  cmd_password = grub_register_command ("legacy_password",
+                                       grub_cmd_legacy_password,
+                                       N_("[--md5] PASSWD [FILE]"),
+                                       N_("Simulate grub-legacy `password' command"));
+
+  cmd_check_password = grub_register_command ("legacy_check_password",
+                                             grub_cmd_legacy_check_password,
+                                             N_("[--md5] PASSWD [FILE]"),
+                                             N_("Simulate grub-legacy `password' command in menu entry mode"));
+
+}
+
+GRUB_MOD_FINI(legacycfg)
+{
+  grub_unregister_command (cmd_source);
+  grub_unregister_command (cmd_configfile);
+  grub_unregister_command (cmd_source_extract);
+  grub_unregister_command (cmd_configfile_extract);
+
+  grub_unregister_command (cmd_kernel);
+  grub_unregister_command (cmd_initrd);
+  grub_unregister_command (cmd_initrdnounzip);
+
+  grub_unregister_command (cmd_password);
+  grub_unregister_command (cmd_check_password);
+}
diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/commands/loadenv.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/commands/loadenv.c
new file mode 100644 (file)
index 0000000..163b9a0
--- /dev/null
@@ -0,0 +1,397 @@
+/* loadenv.c - command to load/save environment variable.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008,2009,2010  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/dl.h>
+#include <grub/mm.h>
+#include <grub/file.h>
+#include <grub/disk.h>
+#include <grub/misc.h>
+#include <grub/env.h>
+#include <grub/partition.h>
+#include <grub/lib/envblk.h>
+#include <grub/extcmd.h>
+#include <grub/i18n.h>
+
+#include "loadenv.h"
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+static const struct grub_arg_option options[] =
+  {
+    /* TRANSLATORS: This option is used to override default filename
+       for loading and storing environment.  */
+    {"file", 'f', 0, N_("Specify filename."), 0, ARG_TYPE_PATHNAME},
+    {"skip-sig", 's', 0,
+     N_("Skip signature-checking of the environment file."), 0, ARG_TYPE_NONE},
+    {0, 0, 0, 0, 0, 0}
+  };
+
+/* Opens 'filename' with compression filters disabled. Optionally disables the
+   PUBKEY filter (that insists upon properly signed files) as well.  PUBKEY
+   filter is restored before the function returns. */
+static grub_file_t
+open_envblk_file (char *filename,
+                 enum grub_file_type type)
+{
+  grub_file_t file;
+  char *buf = 0;
+
+  if (! filename)
+    {
+      const char *prefix;
+      int len;
+
+      prefix = grub_env_get ("prefix");
+      if (! prefix)
+        {
+          grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "prefix");
+          return 0;
+        }
+
+      len = grub_strlen (prefix);
+      buf = grub_malloc (len + 1 + sizeof (GRUB_ENVBLK_DEFCFG));
+      if (! buf)
+        return 0;
+      filename = buf;
+
+      grub_strcpy (filename, prefix);
+      filename[len] = '/';
+      grub_strcpy (filename + len + 1, GRUB_ENVBLK_DEFCFG);
+    }
+
+  file = grub_file_open (filename, type);
+
+  grub_free (buf);
+  return file;
+}
+
+static grub_err_t
+grub_cmd_load_env (grub_extcmd_context_t ctxt, int argc, char **args)
+{
+  struct grub_arg_list *state = ctxt->state;
+  grub_file_t file;
+  grub_envblk_t envblk;
+  grub_env_whitelist_t whitelist;
+
+  whitelist.len = argc;
+  whitelist.list = args;
+
+  /* state[0] is the -f flag; state[1] is the --skip-sig flag */
+  file = open_envblk_file ((state[0].set) ? state[0].arg : 0,
+                          GRUB_FILE_TYPE_LOADENV
+                          | (state[1].set
+                             ? GRUB_FILE_TYPE_SKIP_SIGNATURE : GRUB_FILE_TYPE_NONE));
+  if (! file)
+    return grub_errno;
+
+  envblk = read_envblk_file (file);
+  if (! envblk)
+    goto fail;
+
+  /* argc > 0 indicates caller provided a whitelist of variables to read. */
+  grub_envblk_iterate (envblk, argc > 0 ? &whitelist : 0, set_var);
+  grub_envblk_close (envblk);
+
+ fail:
+  grub_file_close (file);
+  return grub_errno;
+}
+
+/* Print all variables in current context.  */
+static int
+print_var (const char *name, const char *value,
+           void *hook_data __attribute__ ((unused)))
+{
+  grub_printf ("%s=%s\n", name, value);
+  return 0;
+}
+
+static grub_err_t
+grub_cmd_list_env (grub_extcmd_context_t ctxt,
+                  int argc __attribute__ ((unused)),
+                  char **args __attribute__ ((unused)))
+{
+  struct grub_arg_list *state = ctxt->state;
+  grub_file_t file;
+  grub_envblk_t envblk;
+
+  file = open_envblk_file ((state[0].set) ? state[0].arg : 0,
+                          GRUB_FILE_TYPE_LOADENV
+                          | (state[1].set
+                             ? GRUB_FILE_TYPE_SKIP_SIGNATURE : GRUB_FILE_TYPE_NONE));
+  if (! file)
+    return grub_errno;
+
+  envblk = read_envblk_file (file);
+  if (! envblk)
+    goto fail;
+
+  grub_envblk_iterate (envblk, NULL, print_var);
+  grub_envblk_close (envblk);
+
+ fail:
+  grub_file_close (file);
+  return grub_errno;
+}
+
+/* Used to maintain a variable length of blocklists internally.  */
+struct blocklist
+{
+  grub_disk_addr_t sector;
+  unsigned offset;
+  unsigned length;
+  struct blocklist *next;
+};
+
+static void
+free_blocklists (struct blocklist *p)
+{
+  struct blocklist *q;
+
+  for (; p; p = q)
+    {
+      q = p->next;
+      grub_free (p);
+    }
+}
+
+static grub_err_t
+check_blocklists (grub_envblk_t envblk, struct blocklist *blocklists,
+                  grub_file_t file)
+{
+  grub_size_t total_length;
+  grub_size_t index;
+  grub_disk_t disk;
+  grub_disk_addr_t part_start;
+  struct blocklist *p;
+  char *buf;
+
+  /* Sanity checks.  */
+  total_length = 0;
+  for (p = blocklists; p; p = p->next)
+    {
+      struct blocklist *q;
+      /* Check if any pair of blocks overlap.  */
+      for (q = p->next; q; q = q->next)
+        {
+         grub_disk_addr_t s1, s2;
+         grub_disk_addr_t e1, e2;
+
+         s1 = p->sector;
+         e1 = s1 + ((p->length + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS);
+
+         s2 = q->sector;
+         e2 = s2 + ((q->length + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS);
+
+         if (s1 < e2 && s2 < e1)
+            {
+              /* This might be actually valid, but it is unbelievable that
+                 any filesystem makes such a silly allocation.  */
+              return grub_error (GRUB_ERR_BAD_FS, "malformed file");
+            }
+        }
+
+      total_length += p->length;
+    }
+
+  if (total_length != grub_file_size (file))
+    {
+      /* Maybe sparse, unallocated sectors. No way in GRUB.  */
+      return grub_error (GRUB_ERR_BAD_FILE_TYPE, "sparse file not allowed");
+    }
+
+  /* One more sanity check. Re-read all sectors by blocklists, and compare
+     those with the data read via a file.  */
+  disk = file->device->disk;
+
+  part_start = grub_partition_get_start (disk->partition);
+
+  buf = grub_envblk_buffer (envblk);
+  char *blockbuf = NULL;
+  grub_size_t blockbuf_len = 0;
+  for (p = blocklists, index = 0; p; index += p->length, p = p->next)
+    {
+      if (p->length > blockbuf_len)
+       {
+         grub_free (blockbuf);
+         blockbuf_len = 2 * p->length;
+         blockbuf = grub_malloc (blockbuf_len);
+         if (!blockbuf)
+           return grub_errno;
+       }
+
+      if (grub_disk_read (disk, p->sector - part_start,
+                          p->offset, p->length, blockbuf))
+        return grub_errno;
+
+      if (grub_memcmp (buf + index, blockbuf, p->length) != 0)
+       return grub_error (GRUB_ERR_FILE_READ_ERROR, "invalid blocklist");
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+static int
+write_blocklists (grub_envblk_t envblk, struct blocklist *blocklists,
+                  grub_file_t file)
+{
+  char *buf;
+  grub_disk_t disk;
+  grub_disk_addr_t part_start;
+  struct blocklist *p;
+  grub_size_t index;
+
+  buf = grub_envblk_buffer (envblk);
+  disk = file->device->disk;
+  part_start = grub_partition_get_start (disk->partition);
+
+  index = 0;
+  for (p = blocklists; p; index += p->length, p = p->next)
+    {
+      if (grub_disk_write (disk, p->sector - part_start,
+                           p->offset, p->length, buf + index))
+        return 0;
+    }
+
+  return 1;
+}
+
+/* Context for grub_cmd_save_env.  */
+struct grub_cmd_save_env_ctx
+{
+  struct blocklist *head, *tail;
+};
+
+/* Store blocklists in a linked list.  */
+static void
+save_env_read_hook (grub_disk_addr_t sector, unsigned offset, unsigned length,
+                   void *data)
+{
+  struct grub_cmd_save_env_ctx *ctx = data;
+  struct blocklist *block;
+
+  block = grub_malloc (sizeof (*block));
+  if (! block)
+    return;
+
+  block->sector = sector;
+  block->offset = offset;
+  block->length = length;
+
+  /* Slightly complicated, because the list should be FIFO.  */
+  block->next = 0;
+  if (ctx->tail)
+    ctx->tail->next = block;
+  ctx->tail = block;
+  if (! ctx->head)
+    ctx->head = block;
+}
+
+static grub_err_t
+grub_cmd_save_env (grub_extcmd_context_t ctxt, int argc, char **args)
+{
+  struct grub_arg_list *state = ctxt->state;
+  grub_file_t file;
+  grub_envblk_t envblk;
+  struct grub_cmd_save_env_ctx ctx = {
+    .head = 0,
+    .tail = 0
+  };
+
+  if (! argc)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "no variable is specified");
+
+  file = open_envblk_file ((state[0].set) ? state[0].arg : 0,
+                          GRUB_FILE_TYPE_SAVEENV
+                          | GRUB_FILE_TYPE_SKIP_SIGNATURE);
+  if (! file)
+    return grub_errno;
+
+  if (! file->device->disk)
+    {
+      grub_file_close (file);
+      return grub_error (GRUB_ERR_BAD_DEVICE, "disk device required");
+    }
+
+  file->read_hook = save_env_read_hook;
+  file->read_hook_data = &ctx;
+  envblk = read_envblk_file (file);
+  file->read_hook = 0;
+  if (! envblk)
+    goto fail;
+
+  if (check_blocklists (envblk, ctx.head, file))
+    goto fail;
+
+  while (argc)
+    {
+      const char *value;
+
+      value = grub_env_get (args[0]);
+      if (value)
+        {
+          if (! grub_envblk_set (envblk, args[0], value))
+            {
+              grub_error (GRUB_ERR_BAD_ARGUMENT, "environment block too small");
+              goto fail;
+            }
+        }
+      else
+       grub_envblk_delete (envblk, args[0]);
+
+      argc--;
+      args++;
+    }
+
+  write_blocklists (envblk, ctx.head, file);
+
+ fail:
+  if (envblk)
+    grub_envblk_close (envblk);
+  free_blocklists (ctx.head);
+  grub_file_close (file);
+  return grub_errno;
+}
+
+static grub_extcmd_t cmd_load, cmd_list, cmd_save;
+
+GRUB_MOD_INIT(loadenv)
+{
+  cmd_load =
+    grub_register_extcmd ("load_env", grub_cmd_load_env, 0,
+                         N_("[-f FILE] [-s|--skip-sig] [variable_name_to_whitelist] [...]"),
+                         N_("Load variables from environment block file."),
+                         options);
+  cmd_list =
+    grub_register_extcmd ("list_env", grub_cmd_list_env, 0, N_("[-f FILE]"),
+                         N_("List variables from environment block file."),
+                         options);
+  cmd_save =
+    grub_register_extcmd ("save_env", grub_cmd_save_env, 0,
+                         N_("[-f FILE] variable_name [...]"),
+                         N_("Save variables to environment block file."),
+                         options);
+}
+
+GRUB_MOD_FINI(loadenv)
+{
+  grub_unregister_extcmd (cmd_load);
+  grub_unregister_extcmd (cmd_list);
+  grub_unregister_extcmd (cmd_save);
+}
diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/commands/loadenv.h b/GRUB2/MOD_SRC/grub-2.04/grub-core/commands/loadenv.h
new file mode 100644 (file)
index 0000000..952f461
--- /dev/null
@@ -0,0 +1,93 @@
+/* loadenv.c - command to load/save environment variable.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008,2009,2010  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/>.
+ */
+
+static grub_envblk_t UNUSED
+read_envblk_file (grub_file_t file)
+{
+  grub_off_t offset = 0;
+  char *buf;
+  grub_size_t size = grub_file_size (file);
+  grub_envblk_t envblk;
+
+  buf = grub_malloc (size);
+  if (! buf)
+    return 0;
+
+  while (size > 0)
+    {
+      grub_ssize_t ret;
+
+      ret = grub_file_read (file, buf + offset, size);
+      if (ret <= 0)
+        {
+          grub_free (buf);
+          return 0;
+        }
+
+      size -= ret;
+      offset += ret;
+    }
+
+  envblk = grub_envblk_open (buf, offset);
+  if (! envblk)
+    {
+      grub_free (buf);
+      grub_error (GRUB_ERR_BAD_FILE_TYPE, "invalid environment block");
+      return 0;
+    }
+
+  return envblk;
+}
+
+struct grub_env_whitelist
+{
+  grub_size_t len;
+  char **list;
+};
+typedef struct grub_env_whitelist grub_env_whitelist_t;
+
+static int UNUSED
+test_whitelist_membership (const char* name,
+                           const grub_env_whitelist_t* whitelist)
+{
+  grub_size_t i;
+
+  for (i = 0; i < whitelist->len; i++)
+    if (grub_strcmp (name, whitelist->list[i]) == 0)
+      return 1;  /* found it */
+
+  return 0;  /* not found */
+}
+
+/* Helper for grub_cmd_load_env.  */
+static int UNUSED
+set_var (const char *name, const char *value, void *whitelist)
+{
+  if (! whitelist)
+    {
+      grub_env_set (name, value);
+      return 0;
+    }
+
+  if (test_whitelist_membership (name,
+                                (const grub_env_whitelist_t *) whitelist))
+    grub_env_set (name, value);
+
+  return 0;
+}
diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/commands/menuentry.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/commands/menuentry.c
new file mode 100644 (file)
index 0000000..9faf2be
--- /dev/null
@@ -0,0 +1,349 @@
+/* menuentry.c - menuentry command */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2010  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/types.h>
+#include <grub/misc.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/extcmd.h>
+#include <grub/i18n.h>
+#include <grub/normal.h>
+
+static const struct grub_arg_option options[] =
+  {
+    {"class", 1, GRUB_ARG_OPTION_REPEATABLE,
+     N_("Menu entry type."), N_("STRING"), ARG_TYPE_STRING},
+    {"users", 2, 0,
+     N_("List of users allowed to boot this entry."), N_("USERNAME[,USERNAME]"),
+     ARG_TYPE_STRING},
+    {"hotkey", 3, 0,
+     N_("Keyboard key to quickly boot this entry."), N_("KEYBOARD_KEY"), ARG_TYPE_STRING},
+    {"source", 4, 0,
+     N_("Use STRING as menu entry body."), N_("STRING"), ARG_TYPE_STRING},
+    {"id", 0, 0, N_("Menu entry identifier."), N_("STRING"), ARG_TYPE_STRING},
+    /* TRANSLATORS: menu entry can either be bootable by anyone or only by
+       handful of users. By default when security is active only superusers can
+       boot a given menu entry. With --unrestricted (this option)
+       anyone can boot it.  */
+    {"unrestricted", 0, 0, N_("This entry can be booted by any user."),
+     0, ARG_TYPE_NONE},
+    {0, 0, 0, 0, 0, 0}
+  };
+
+static struct
+{
+  const char *name;
+  int key;
+} hotkey_aliases[] =
+  {
+    {"backspace", GRUB_TERM_BACKSPACE},
+    {"tab", GRUB_TERM_TAB},
+    {"delete", GRUB_TERM_KEY_DC},
+    {"insert", GRUB_TERM_KEY_INSERT},
+    {"f1", GRUB_TERM_KEY_F1},
+    {"f2", GRUB_TERM_KEY_F2},
+    {"f3", GRUB_TERM_KEY_F3},
+    {"f4", GRUB_TERM_KEY_F4},
+    {"f5", GRUB_TERM_KEY_F5},
+    {"f6", GRUB_TERM_KEY_F6},
+    {"f7", GRUB_TERM_KEY_F7},
+    {"f8", GRUB_TERM_KEY_F8},
+    {"f9", GRUB_TERM_KEY_F9},
+    {"f10", GRUB_TERM_KEY_F10},
+    {"f11", GRUB_TERM_KEY_F11},
+    {"f12", GRUB_TERM_KEY_F12},
+  };
+
+/* Add a menu entry to the current menu context (as given by the environment
+   variable data slot `menu').  As the configuration file is read, the script
+   parser calls this when a menu entry is to be created.  */
+grub_err_t
+grub_normal_add_menu_entry (int argc, const char **args,
+                           char **classes, const char *id,
+                           const char *users, const char *hotkey,
+                           const char *prefix, const char *sourcecode,
+                           int submenu, int *index, struct bls_entry *bls)
+{
+  int menu_hotkey = 0;
+  char **menu_args = NULL;
+  char *menu_users = NULL;
+  char *menu_title = NULL;
+  char *menu_sourcecode = NULL;
+  char *menu_id = NULL;
+  struct grub_menu_entry_class *menu_classes = NULL;
+
+  grub_menu_t menu;
+  grub_menu_entry_t *last;
+
+  menu = grub_env_get_menu ();
+  if (! menu)
+    return grub_error (GRUB_ERR_MENU, "no menu context");
+
+  last = &menu->entry_list;
+
+  menu_sourcecode = grub_xasprintf ("%s%s", prefix ?: "", sourcecode);
+  if (! menu_sourcecode)
+    return grub_errno;
+
+  if (classes && classes[0])
+    {
+      int i;
+      for (i = 0; classes[i]; i++); /* count # of menuentry classes */
+      menu_classes = grub_zalloc (sizeof (struct grub_menu_entry_class)
+                                 * (i + 1));
+      if (! menu_classes)
+       goto fail;
+
+      for (i = 0; classes[i]; i++)
+       {
+         menu_classes[i].name = grub_strdup (classes[i]);
+         if (! menu_classes[i].name)
+           goto fail;
+         menu_classes[i].next = classes[i + 1] ? &menu_classes[i + 1] : NULL;
+       }
+    }
+
+  if (users)
+    {
+      menu_users = grub_strdup (users);
+      if (! menu_users)
+       goto fail;
+    }
+
+  if (hotkey)
+    {
+      unsigned i;
+      for (i = 0; i < ARRAY_SIZE (hotkey_aliases); i++)
+       if (grub_strcmp (hotkey, hotkey_aliases[i].name) == 0)
+         {
+           menu_hotkey = hotkey_aliases[i].key;
+           break;
+         }
+      if (i == ARRAY_SIZE (hotkey_aliases))
+       menu_hotkey = hotkey[0];
+    }
+
+  if (! argc)
+    {
+      grub_error (GRUB_ERR_MENU, "menuentry is missing title");
+      goto fail;
+    }
+
+  menu_title = grub_strdup (args[0]);
+  if (! menu_title)
+    goto fail;
+
+  grub_dprintf ("menu", "id:\"%s\"\n", id);
+  grub_dprintf ("menu", "title:\"%s\"\n", menu_title);
+  menu_id = grub_strdup (id ? : menu_title);
+  if (! menu_id)
+    goto fail;
+  grub_dprintf ("menu", "menu_id:\"%s\"\n", menu_id);
+
+  /* Save argc, args to pass as parameters to block arg later. */
+  menu_args = grub_malloc (sizeof (char*) * (argc + 1));
+  if (! menu_args)
+    goto fail;
+
+  {
+    int i;
+    for (i = 0; i < argc; i++)
+      {
+       menu_args[i] = grub_strdup (args[i]);
+       if (! menu_args[i])
+         goto fail;
+      }
+    menu_args[argc] = NULL;
+  }
+
+  /* Add the menu entry at the end of the list.  */
+  int ind=0;
+  while (*last)
+    {
+      ind++;
+      last = &(*last)->next;
+    }
+
+  *last = grub_zalloc (sizeof (**last));
+  if (! *last)
+    goto fail;
+
+  (*last)->title = menu_title;
+  (*last)->id = menu_id;
+  (*last)->hotkey = menu_hotkey;
+  (*last)->classes = menu_classes;
+  if (menu_users)
+    (*last)->restricted = 1;
+  (*last)->users = menu_users;
+  (*last)->argc = argc;
+  (*last)->args = menu_args;
+  (*last)->sourcecode = menu_sourcecode;
+  (*last)->submenu = submenu;
+  (*last)->bls = bls;
+
+  menu->size++;
+  if (index)
+    *index = ind;
+  return GRUB_ERR_NONE;
+
+ fail:
+
+  grub_free (menu_sourcecode);
+  {
+    int i;
+    for (i = 0; menu_classes && menu_classes[i].name; i++)
+      grub_free (menu_classes[i].name);
+    grub_free (menu_classes);
+  }
+
+  {
+    int i;
+    for (i = 0; menu_args && menu_args[i]; i++)
+      grub_free (menu_args[i]);
+    grub_free (menu_args);
+  }
+
+  grub_free (menu_users);
+  grub_free (menu_title);
+  grub_free (menu_id);
+  return grub_errno;
+}
+
+static char *
+setparams_prefix (int argc, char **args)
+{
+  int i;
+  int j;
+  char *p;
+  char *result;
+  grub_size_t len = 10;
+
+  /* Count resulting string length */
+  for (i = 0; i < argc; i++)
+    {
+      len += 3; /* 3 = 1 space + 2 quotes */
+      p = args[i];
+      while (*p)
+       len += (*p++ == '\'' ? 3 : 1);
+    }
+
+  result = grub_malloc (len + 2);
+  if (! result)
+    return 0;
+
+  grub_strcpy (result, "setparams");
+  p = result + 9;
+
+  for (j = 0; j < argc; j++)
+    {
+      *p++ = ' ';
+      *p++ = '\'';
+      p = grub_strchrsub (p, args[j], '\'', "'\\''");
+      *p++ = '\'';
+    }
+  *p++ = '\n';
+  *p = '\0';
+  return result;
+}
+
+static grub_err_t
+grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args)
+{
+  char ch;
+  char *src;
+  char *prefix;
+  unsigned len;
+  grub_err_t r;
+  const char *users;
+
+  if (! argc)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing arguments");
+
+  if (ctxt->state[3].set && ctxt->script)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "multiple menuentry definitions");
+
+  if (! ctxt->state[3].set && ! ctxt->script)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "no menuentry definition");
+
+  if (ctxt->state[1].set)
+    users = ctxt->state[1].arg;
+  else if (ctxt->state[5].set)
+    users = NULL;
+  else
+    users = "";
+
+  if (! ctxt->script)
+    return grub_normal_add_menu_entry (argc, (const char **) args,
+                                      (ctxt->state[0].set ? ctxt->state[0].args
+                                       : NULL),
+                                      ctxt->state[4].arg,
+                                      users,
+                                      ctxt->state[2].arg, 0,
+                                      ctxt->state[3].arg,
+                                      ctxt->extcmd->cmd->name[0] == 's',
+                                      NULL, NULL);
+
+  src = args[argc - 1];
+  args[argc - 1] = NULL;
+
+  len = grub_strlen(src);
+  ch = src[len - 1];
+  src[len - 1] = '\0';
+
+  prefix = setparams_prefix (argc - 1, args);
+  if (! prefix)
+    return grub_errno;
+
+  r = grub_normal_add_menu_entry (argc - 1, (const char **) args,
+                                 ctxt->state[0].args, ctxt->state[4].arg,
+                                 users,
+                                 ctxt->state[2].arg, prefix, src + 1,
+                                 ctxt->extcmd->cmd->name[0] == 's', NULL,
+                                 NULL);
+
+  src[len - 1] = ch;
+  args[argc - 1] = src;
+  grub_free (prefix);
+  return r;
+}
+
+static grub_extcmd_t cmd, cmd_sub;
+
+void
+grub_menu_init (void)
+{
+  cmd = grub_register_extcmd ("menuentry", grub_cmd_menuentry,
+                             GRUB_COMMAND_FLAG_BLOCKS
+                             | GRUB_COMMAND_ACCEPT_DASH
+                             | GRUB_COMMAND_FLAG_EXTRACTOR,
+                             N_("BLOCK"), N_("Define a menu entry."), options);
+  cmd_sub = grub_register_extcmd ("submenu", grub_cmd_menuentry,
+                                 GRUB_COMMAND_FLAG_BLOCKS
+                                 | GRUB_COMMAND_ACCEPT_DASH
+                                 | GRUB_COMMAND_FLAG_EXTRACTOR,
+                                 N_("BLOCK"), N_("Define a submenu."),
+                                 options);
+}
+
+void
+grub_menu_fini (void)
+{
+  grub_unregister_extcmd (cmd);
+  grub_unregister_extcmd (cmd_sub);
+}
index 2f22ecb56a53e1192beede96130cbb8b8af4572b..42bc22f717530d4b91c58f8e486e82636b86d5ce 100644 (file)
@@ -109,6 +109,52 @@ grub_env_write_root (struct grub_env_var *var __attribute__ ((unused)),
   return grub_strdup (val);
 }
 
+static int g_ventoy_hook_root = 0;
+void ventoy_env_hook_root(int hook)
+{
+    g_ventoy_hook_root = hook;
+}
+
+static char *
+ventoy_env_write_root (struct grub_env_var *var __attribute__ ((unused)),
+                    const char *val)
+{
+    const char *pos = val;
+    char buf[256];
+    
+    if (g_ventoy_hook_root == 0)
+    {
+        return grub_env_write_root(var, val);
+    }
+
+    if (pos[0] == '(')
+    {
+        pos++;
+    }
+
+    if (grub_strncmp(pos, "vtimghd", 7) == 0)
+    {
+        return grub_env_write_root(var, val);
+    }
+
+    pos = grub_strchr(val, ',');
+    if (!pos)
+    {
+        return grub_env_write_root(var, val);
+    }
+
+    if (val[0] == '(')
+    {
+        grub_snprintf(buf, sizeof(buf), "(vtimghd%s", pos);
+    }
+    else
+    {
+        grub_snprintf(buf, sizeof(buf), "vtimghd%s", pos);
+    }
+
+    return grub_env_write_root(var, buf);
+}
+
 static void
 grub_set_prefix_and_root (void)
 {
@@ -123,7 +169,7 @@ grub_set_prefix_and_root (void)
     if (header->type == OBJ_TYPE_PREFIX)
       prefix = (char *) header + sizeof (struct grub_module_header);
 
-  grub_register_variable_hook ("root", 0, grub_env_write_root);
+  grub_register_variable_hook ("root", 0, ventoy_env_write_root);
 
   grub_machine_get_bootlocation (&fwdevice, &fwpath);
 
diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/loader/i386/linux.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/loader/i386/linux.c
new file mode 100644 (file)
index 0000000..6601d5d
--- /dev/null
@@ -0,0 +1,1470 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006,2007,2008,2009,2010  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/loader.h>
+#include <grub/memory.h>
+#include <grub/normal.h>
+#include <grub/file.h>
+#include <grub/disk.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/term.h>
+#include <grub/cpu/linux.h>
+#include <grub/video.h>
+#include <grub/video_fb.h>
+#include <grub/command.h>
+#include <grub/i386/relocator.h>
+#include <grub/i18n.h>
+#include <grub/lib/cmdline.h>
+#include <grub/linux.h>
+#include <grub/machine/kernel.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+#ifdef GRUB_MACHINE_PCBIOS
+#include <grub/i386/pc/vesa_modes_table.h>
+#endif
+
+#ifdef GRUB_MACHINE_EFI
+#include <grub/efi/efi.h>
+#define HAS_VGA_TEXT 0
+#define DEFAULT_VIDEO_MODE "auto"
+#define ACCEPTS_PURE_TEXT 0
+#elif defined (GRUB_MACHINE_IEEE1275)
+#include <grub/ieee1275/ieee1275.h>
+#define HAS_VGA_TEXT 0
+#define DEFAULT_VIDEO_MODE "text"
+#define ACCEPTS_PURE_TEXT 1
+#else
+#include <grub/i386/pc/vbe.h>
+#include <grub/i386/pc/console.h>
+#define HAS_VGA_TEXT 1
+#define DEFAULT_VIDEO_MODE "text"
+#define ACCEPTS_PURE_TEXT 1
+#endif
+
+static grub_dl_t my_mod;
+
+static grub_size_t linux_mem_size;
+static int loaded;
+static void *prot_mode_mem;
+static grub_addr_t prot_mode_target;
+static void *initrd_mem;
+static grub_addr_t initrd_mem_target;
+static grub_size_t prot_init_space;
+static struct grub_relocator *relocator = NULL;
+static void *efi_mmap_buf;
+static grub_size_t maximal_cmdline_size;
+static struct linux_kernel_params linux_params;
+static char *linux_cmdline;
+#ifdef GRUB_MACHINE_EFI
+static grub_efi_uintn_t efi_mmap_size;
+#else
+static const grub_size_t efi_mmap_size = 0;
+#endif
+
+#define LINUX_MAX_ARGC  1024
+static int ventoy_debug = 0;
+static int ventoy_initrd_called = 0;
+static int ventoy_linux_argc = 0;
+static char **ventoy_linux_args = NULL;
+static grub_err_t
+grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]);
+
+/* FIXME */
+#if 0
+struct idt_descriptor
+{
+  grub_uint16_t limit;
+  void *base;
+} GRUB_PACKED;
+
+static struct idt_descriptor idt_desc =
+  {
+    0,
+    0
+  };
+#endif
+
+static inline grub_size_t
+page_align (grub_size_t size)
+{
+  return (size + (1 << 12) - 1) & (~((1 << 12) - 1));
+}
+
+/* Helper for find_mmap_size.  */
+static int
+count_hook (grub_uint64_t addr __attribute__ ((unused)),
+           grub_uint64_t size __attribute__ ((unused)),
+           grub_memory_type_t type __attribute__ ((unused)), void *data)
+{
+  grub_size_t *count = data;
+
+  (*count)++;
+  return 0;
+}
+
+/* Find the optimal number of pages for the memory map. */
+static grub_size_t
+find_mmap_size (void)
+{
+  grub_size_t count = 0, mmap_size;
+
+  grub_mmap_iterate (count_hook, &count);
+
+  mmap_size = count * sizeof (struct grub_e820_mmap);
+
+  /* Increase the size a bit for safety, because GRUB allocates more on
+     later.  */
+  mmap_size += (1 << 12);
+
+  return page_align (mmap_size);
+}
+
+static void
+free_pages (void)
+{
+  grub_relocator_unload (relocator);
+  relocator = NULL;
+  prot_mode_mem = initrd_mem = 0;
+  prot_mode_target = initrd_mem_target = 0;
+}
+
+/* Allocate pages for the real mode code and the protected mode code
+   for linux as well as a memory map buffer.  */
+static grub_err_t
+allocate_pages (grub_size_t prot_size, grub_size_t *align,
+               grub_size_t min_align, int relocatable,
+               grub_uint64_t preferred_address)
+{
+  grub_err_t err;
+
+  if (prot_size == 0)
+    prot_size = 1;
+
+  prot_size = page_align (prot_size);
+
+  /* Initialize the memory pointers with NULL for convenience.  */
+  free_pages ();
+
+  relocator = grub_relocator_new ();
+  if (!relocator)
+    {
+      err = grub_errno;
+      goto fail;
+    }
+
+  /* FIXME: Should request low memory from the heap when this feature is
+     implemented.  */
+
+  {
+    grub_relocator_chunk_t ch;
+    if (relocatable)
+      {
+       err = grub_relocator_alloc_chunk_align (relocator, &ch,
+                                               preferred_address,
+                                               preferred_address,
+                                               prot_size, 1,
+                                               GRUB_RELOCATOR_PREFERENCE_LOW,
+                                               1);
+       for (; err && *align + 1 > min_align; (*align)--)
+         {
+           grub_errno = GRUB_ERR_NONE;
+           err = grub_relocator_alloc_chunk_align (relocator, &ch,
+                                                   0x1000000,
+                                                   0xffffffff & ~prot_size,
+                                                   prot_size, 1 << *align,
+                                                   GRUB_RELOCATOR_PREFERENCE_LOW,
+                                                   1);
+         }
+       if (err)
+         goto fail;
+      }
+    else
+      err = grub_relocator_alloc_chunk_addr (relocator, &ch,
+                                            preferred_address,
+                                            prot_size);
+    if (err)
+      goto fail;
+    prot_mode_mem = get_virtual_current_address (ch);
+    prot_mode_target = get_physical_target_address (ch);
+  }
+
+  grub_dprintf ("linux", "prot_mode_mem = %p, prot_mode_target = %lx, prot_size = %x\n",
+                prot_mode_mem, (unsigned long) prot_mode_target,
+               (unsigned) prot_size);
+  return GRUB_ERR_NONE;
+
+ fail:
+  free_pages ();
+  return err;
+}
+
+static grub_err_t
+grub_e820_add_region (struct grub_e820_mmap *e820_map, int *e820_num,
+                      grub_uint64_t start, grub_uint64_t size,
+                      grub_uint32_t type)
+{
+  int n = *e820_num;
+
+  if ((n > 0) && (e820_map[n - 1].addr + e820_map[n - 1].size == start) &&
+      (e820_map[n - 1].type == type))
+      e820_map[n - 1].size += size;
+  else
+    {
+      e820_map[n].addr = start;
+      e820_map[n].size = size;
+      e820_map[n].type = type;
+      (*e820_num)++;
+    }
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_linux_setup_video (struct linux_kernel_params *params)
+{
+  struct grub_video_mode_info mode_info;
+  void *framebuffer;
+  grub_err_t err;
+  grub_video_driver_id_t driver_id;
+  const char *gfxlfbvar = grub_env_get ("gfxpayloadforcelfb");
+
+  driver_id = grub_video_get_driver_id ();
+
+  if (driver_id == GRUB_VIDEO_DRIVER_NONE)
+    return 1;
+
+  err = grub_video_get_info_and_fini (&mode_info, &framebuffer);
+
+  if (err)
+    {
+      grub_errno = GRUB_ERR_NONE;
+      return 1;
+    }
+
+  params->lfb_width = mode_info.width;
+  params->lfb_height = mode_info.height;
+  params->lfb_depth = mode_info.bpp;
+  params->lfb_line_len = mode_info.pitch;
+
+  params->lfb_base = (grub_size_t) framebuffer;
+
+#if defined (GRUB_MACHINE_EFI) && defined (__x86_64__)
+  params->ext_lfb_base = (grub_size_t) (((grub_uint64_t)(grub_size_t) framebuffer) >> 32);
+  params->capabilities |= VIDEO_CAPABILITY_64BIT_BASE;
+#endif
+
+  params->lfb_size = ALIGN_UP (params->lfb_line_len * params->lfb_height, 65536);
+
+  params->red_mask_size = mode_info.red_mask_size;
+  params->red_field_pos = mode_info.red_field_pos;
+  params->green_mask_size = mode_info.green_mask_size;
+  params->green_field_pos = mode_info.green_field_pos;
+  params->blue_mask_size = mode_info.blue_mask_size;
+  params->blue_field_pos = mode_info.blue_field_pos;
+  params->reserved_mask_size = mode_info.reserved_mask_size;
+  params->reserved_field_pos = mode_info.reserved_field_pos;
+
+  if (gfxlfbvar && (gfxlfbvar[0] == '1' || gfxlfbvar[0] == 'y'))
+    params->have_vga = GRUB_VIDEO_LINUX_TYPE_SIMPLE;
+  else
+    {
+      switch (driver_id)
+       {
+       case GRUB_VIDEO_DRIVER_VBE:
+         params->lfb_size >>= 16;
+         params->have_vga = GRUB_VIDEO_LINUX_TYPE_VESA;
+         break;
+       
+       case GRUB_VIDEO_DRIVER_EFI_UGA:
+       case GRUB_VIDEO_DRIVER_EFI_GOP:
+         params->have_vga = GRUB_VIDEO_LINUX_TYPE_EFIFB;
+         break;
+
+         /* FIXME: check if better id is available.  */
+       case GRUB_VIDEO_DRIVER_SM712:
+       case GRUB_VIDEO_DRIVER_SIS315PRO:
+       case GRUB_VIDEO_DRIVER_VGA:
+       case GRUB_VIDEO_DRIVER_CIRRUS:
+       case GRUB_VIDEO_DRIVER_BOCHS:
+       case GRUB_VIDEO_DRIVER_RADEON_FULOONG2E:
+       case GRUB_VIDEO_DRIVER_RADEON_YEELOONG3A:
+       case GRUB_VIDEO_DRIVER_IEEE1275:
+       case GRUB_VIDEO_DRIVER_COREBOOT:
+         /* Make gcc happy. */
+       case GRUB_VIDEO_DRIVER_XEN:
+       case GRUB_VIDEO_DRIVER_SDL:
+       case GRUB_VIDEO_DRIVER_NONE:
+       case GRUB_VIDEO_ADAPTER_CAPTURE:
+         params->have_vga = GRUB_VIDEO_LINUX_TYPE_SIMPLE;
+         break;
+       }
+    }
+
+#ifdef GRUB_MACHINE_PCBIOS
+  /* VESA packed modes may come with zeroed mask sizes, which need
+     to be set here according to DAC Palette width.  If we don't,
+     this results in Linux displaying a black screen.  */
+  if (driver_id == GRUB_VIDEO_DRIVER_VBE && mode_info.bpp <= 8)
+    {
+      struct grub_vbe_info_block controller_info;
+      int status;
+      int width = 8;
+
+      status = grub_vbe_bios_get_controller_info (&controller_info);
+
+      if (status == GRUB_VBE_STATUS_OK &&
+         (controller_info.capabilities & GRUB_VBE_CAPABILITY_DACWIDTH))
+       status = grub_vbe_bios_set_dac_palette_width (&width);
+
+      if (status != GRUB_VBE_STATUS_OK)
+       /* 6 is default after mode reset.  */
+       width = 6;
+
+      params->red_mask_size = params->green_mask_size
+       = params->blue_mask_size = width;
+      params->reserved_mask_size = 0;
+    }
+#endif
+
+  return GRUB_ERR_NONE;
+}
+
+/* Context for grub_linux_boot.  */
+struct grub_linux_boot_ctx
+{
+  grub_addr_t real_mode_target;
+  grub_size_t real_size;
+  struct linux_kernel_params *params;
+  int e820_num;
+};
+
+/* Helper for grub_linux_boot.  */
+static int
+grub_linux_boot_mmap_find (grub_uint64_t addr, grub_uint64_t size,
+                          grub_memory_type_t type, void *data)
+{
+  struct grub_linux_boot_ctx *ctx = data;
+
+  /* We must put real mode code in the traditional space.  */
+  if (type != GRUB_MEMORY_AVAILABLE || addr > 0x90000)
+    return 0;
+
+  if (addr + size < 0x10000)
+    return 0;
+
+  if (addr < 0x10000)
+    {
+      size += addr - 0x10000;
+      addr = 0x10000;
+    }
+
+  if (addr + size > 0x90000)
+    size = 0x90000 - addr;
+
+  if (ctx->real_size + efi_mmap_size > size)
+    return 0;
+
+  grub_dprintf ("linux", "addr = %lx, size = %x, need_size = %x\n",
+               (unsigned long) addr,
+               (unsigned) size,
+               (unsigned) (ctx->real_size + efi_mmap_size));
+  ctx->real_mode_target = ((addr + size) - (ctx->real_size + efi_mmap_size));
+  return 1;
+}
+
+/* GRUB types conveniently match E820 types.  */
+static int
+grub_linux_boot_mmap_fill (grub_uint64_t addr, grub_uint64_t size,
+                          grub_memory_type_t type, void *data)
+{
+  struct grub_linux_boot_ctx *ctx = data;
+
+  if (grub_e820_add_region (ctx->params->e820_map, &ctx->e820_num,
+                           addr, size, type))
+    return 1;
+
+  return 0;
+}
+
+static void ventoy_debug_pause(void)
+{
+    char key;
+
+    if (0 == ventoy_debug) 
+    {
+        return;
+    }
+    
+    grub_printf("press Enter to continue ......\n");
+    while (1)
+    {
+        key = grub_getkey();
+        if (key == '\n' || key == '\r')
+        {
+            break;
+        }
+    }    
+}
+
+static int ventoy_preboot(void)
+{
+    char buf[128];
+    char *argv[2];
+
+    if (ventoy_debug) 
+    {
+        grub_printf("ventoy_preboot %d %d\n", ventoy_linux_argc, ventoy_initrd_called);
+        ventoy_debug_pause();
+    }
+
+    if (ventoy_linux_argc == 0)
+    {
+        return 0;
+    }
+
+    if (ventoy_initrd_called)
+    {
+        ventoy_initrd_called = 0;
+        return 0;
+    }
+
+    grub_snprintf(buf, sizeof(buf), "mem:%s:size:%s", grub_env_get("ventoy_cpio_addr"), grub_env_get("ventoy_cpio_size"));
+
+    argv[0] = buf;
+    argv[1] = NULL;
+    grub_cmd_initrd(NULL, 1, argv);
+
+    if (ventoy_debug) 
+    {
+        grub_printf("add initrd %s\n", buf);
+        ventoy_debug_pause();
+    }
+
+    return 0;
+}
+
+static int ventoy_boot_opt_filter(char *opt)
+{
+    if (grub_strcmp(opt, "noinitrd") == 0)
+    {
+        return 1;
+    }
+
+    if (grub_strncmp(opt, "rdinit=", 7) == 0)
+    {
+        if (grub_strcmp(opt, "rdinit=/vtoy/vtoy") != 0)
+        {
+            opt[0] = 'v';
+            opt[1] = 't';
+        }
+        return 0;
+    }
+
+    if (ventoy_debug)
+    {
+        if (grub_strcmp(opt, "quiet") == 0)
+        {
+            return 1;
+        }
+        
+        if (grub_strncmp(opt, "loglevel=", 9) == 0)
+        {
+            return 1;
+        }
+        
+        if (grub_strcmp(opt, "splash") == 0)
+        {
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+static int ventoy_bootopt_hook(int argc, char *argv[])
+{
+    int i;
+    int count = 0;
+    const char *env;
+    char c;
+    char *newenv;
+    char *last, *pos;
+
+    //grub_printf("ventoy_bootopt_hook: %d %d\n", argc, ventoy_linux_argc);
+
+    if (ventoy_linux_argc == 0)
+    {
+        return 0;
+    }
+
+    for (i = 0; i < argc; i++)
+    {
+        if (ventoy_boot_opt_filter(argv[i]))
+        {
+            continue;
+        }
+
+        ventoy_linux_args[count++] = grub_strdup(argv[i]);
+    }
+
+    for (i = 0; i < ventoy_linux_argc; i++)
+    {
+        ventoy_linux_args[count] = ventoy_linux_args[i + (LINUX_MAX_ARGC / 2)];
+        ventoy_linux_args[i + (LINUX_MAX_ARGC / 2)] = NULL;
+        
+        if (ventoy_linux_args[count][0] == '@')
+        {
+            env = grub_env_get(ventoy_linux_args[count] + 1);
+            if (env)
+            {
+                grub_free(ventoy_linux_args[count]);
+
+                newenv = grub_strdup(env);
+                last =  newenv;
+
+                while (*last)
+                {
+                    while (*last)
+                    {
+                        if (*last != ' ' && *last != '\t')
+                        {
+                            break;
+                        }
+                        last++;
+                    }
+
+                    if (*last == 0)
+                    {
+                        break;
+                    }
+
+                    for (pos = last; *pos; pos++)
+                    {
+                        if (*pos == ' ' || *pos == '\t')
+                        {
+                            c = *pos;
+                            *pos = 0;
+                            if (0 == ventoy_boot_opt_filter(last))
+                            {
+                                ventoy_linux_args[count++] = grub_strdup(last);
+                            }
+                            *pos = c;
+                            break;
+                        }
+                    }
+
+                    if (*pos == 0)
+                    {
+                        if (0 == ventoy_boot_opt_filter(last))
+                        {
+                            ventoy_linux_args[count++] = grub_strdup(last);                            
+                        }
+                        break;
+                    }
+
+                    last = pos + 1;
+                }
+            }
+            else
+            {
+                count++;
+            }
+        }
+        else
+        {
+            count++;            
+        }
+    }
+
+    if (ventoy_debug)
+    {
+        ventoy_linux_args[count++] = grub_strdup("loglevel=10");
+    }
+
+    ventoy_linux_argc = count;
+
+    if (ventoy_debug)
+    {
+        grub_printf("========== bootoption ==========\n");
+        for (i = 0; i < count; i++)
+        {
+            grub_printf("%s ", ventoy_linux_args[i]);
+        }  
+        grub_printf("\n================================\n");
+    }
+    
+    return 0;
+}
+
+static grub_err_t
+grub_cmd_set_boot_opt (grub_command_t cmd __attribute__ ((unused)),
+               int argc, char *argv[])
+{
+    int i;
+    const char *vtdebug;
+
+    for (i = 0; i < argc; i++)
+    {
+        ventoy_linux_args[ventoy_linux_argc + (LINUX_MAX_ARGC / 2) ] = grub_strdup(argv[i]);
+        ventoy_linux_argc++;
+    }
+
+    vtdebug = grub_env_get("vtdebug_flag");
+    if (vtdebug && vtdebug[0])
+    {
+        ventoy_debug = 1;
+    }
+
+    if (ventoy_debug) grub_printf("ventoy set boot opt %d\n", ventoy_linux_argc);
+
+    return 0;
+}
+
+static grub_err_t
+grub_cmd_unset_boot_opt (grub_command_t cmd __attribute__ ((unused)),
+               int argc, char *argv[])
+{
+    int i;
+    
+    (void)argc;
+    (void)argv;
+
+    for (i = 0; i < LINUX_MAX_ARGC; i++)
+    {
+        if (ventoy_linux_args[i])
+        {
+            grub_free(ventoy_linux_args[i]);
+        }
+    }
+
+    ventoy_debug = 0;
+    ventoy_linux_argc = 0;
+    ventoy_initrd_called = 0;
+    grub_memset(ventoy_linux_args, 0, sizeof(char *) * LINUX_MAX_ARGC);
+    return 0;
+}
+
+
+static grub_err_t
+grub_linux_boot (void)
+{
+  grub_err_t err = 0;
+  const char *modevar;
+  char *tmp;
+  struct grub_relocator32_state state;
+  void *real_mode_mem;
+  struct grub_linux_boot_ctx ctx = {
+    .real_mode_target = 0
+  };
+  grub_size_t mmap_size;
+  grub_size_t cl_offset;
+
+  ventoy_preboot();
+
+#ifdef GRUB_MACHINE_IEEE1275
+  {
+    const char *bootpath;
+    grub_ssize_t len;
+
+    bootpath = grub_env_get ("root");
+    if (bootpath)
+      grub_ieee1275_set_property (grub_ieee1275_chosen,
+                                 "bootpath", bootpath,
+                                 grub_strlen (bootpath) + 1,
+                                 &len);
+    linux_params.ofw_signature = GRUB_LINUX_OFW_SIGNATURE;
+    linux_params.ofw_num_items = 1;
+    linux_params.ofw_cif_handler = (grub_uint32_t) grub_ieee1275_entry_fn;
+    linux_params.ofw_idt = 0;
+  }
+#endif
+
+  modevar = grub_env_get ("gfxpayload");
+
+  /* Now all graphical modes are acceptable.
+     May change in future if we have modes without framebuffer.  */
+  if (modevar && *modevar != 0)
+    {
+      tmp = grub_xasprintf ("%s;" DEFAULT_VIDEO_MODE, modevar);
+      if (! tmp)
+       return grub_errno;
+#if ACCEPTS_PURE_TEXT
+      err = grub_video_set_mode (tmp, 0, 0);
+#else
+      err = grub_video_set_mode (tmp, GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0);
+#endif
+      grub_free (tmp);
+    }
+  else       /* We can't go back to text mode from coreboot fb.  */
+#ifdef GRUB_MACHINE_COREBOOT
+    if (grub_video_get_driver_id () == GRUB_VIDEO_DRIVER_COREBOOT)
+      err = GRUB_ERR_NONE;
+    else
+#endif
+      {
+#if ACCEPTS_PURE_TEXT
+       err = grub_video_set_mode (DEFAULT_VIDEO_MODE, 0, 0);
+#else
+       err = grub_video_set_mode (DEFAULT_VIDEO_MODE,
+                                GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0);
+#endif
+      }
+
+  if (err)
+    {
+      grub_print_error ();
+      grub_puts_ (N_("Booting in blind mode"));
+      grub_errno = GRUB_ERR_NONE;
+    }
+
+  if (grub_linux_setup_video (&linux_params))
+    {
+#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU)
+      linux_params.have_vga = GRUB_VIDEO_LINUX_TYPE_TEXT;
+      linux_params.video_mode = 0x3;
+#else
+      linux_params.have_vga = 0;
+      linux_params.video_mode = 0;
+      linux_params.video_width = 0;
+      linux_params.video_height = 0;
+#endif
+    }
+
+
+#ifndef GRUB_MACHINE_IEEE1275
+  if (linux_params.have_vga == GRUB_VIDEO_LINUX_TYPE_TEXT)
+#endif
+    {
+      grub_term_output_t term;
+      int found = 0;
+      FOR_ACTIVE_TERM_OUTPUTS(term)
+       if (grub_strcmp (term->name, "vga_text") == 0
+           || grub_strcmp (term->name, "console") == 0
+           || grub_strcmp (term->name, "ofconsole") == 0)
+         {
+           struct grub_term_coordinate pos = grub_term_getxy (term);
+           linux_params.video_cursor_x = pos.x;
+           linux_params.video_cursor_y = pos.y;
+           linux_params.video_width = grub_term_width (term);
+           linux_params.video_height = grub_term_height (term);
+           found = 1;
+           break;
+         }
+      if (!found)
+       {
+         linux_params.video_cursor_x = 0;
+         linux_params.video_cursor_y = 0;
+         linux_params.video_width = 80;
+         linux_params.video_height = 25;
+       }
+    }
+
+#ifdef GRUB_KERNEL_USE_RSDP_ADDR
+  linux_params.acpi_rsdp_addr = grub_le_to_cpu64 (grub_rsdp_addr);
+#endif
+
+  mmap_size = find_mmap_size ();
+  /* Make sure that each size is aligned to a page boundary.  */
+  cl_offset = ALIGN_UP (mmap_size + sizeof (linux_params), 4096);
+  if (cl_offset < ((grub_size_t) linux_params.setup_sects << GRUB_DISK_SECTOR_BITS))
+    cl_offset = ALIGN_UP ((grub_size_t) (linux_params.setup_sects
+                                        << GRUB_DISK_SECTOR_BITS), 4096);
+  ctx.real_size = ALIGN_UP (cl_offset + maximal_cmdline_size, 4096);
+
+#ifdef GRUB_MACHINE_EFI
+  efi_mmap_size = grub_efi_find_mmap_size ();
+  if (efi_mmap_size == 0)
+    return grub_errno;
+#endif
+
+  grub_dprintf ("linux", "real_size = %x, mmap_size = %x\n",
+               (unsigned) ctx.real_size, (unsigned) mmap_size);
+
+#ifdef GRUB_MACHINE_EFI
+  grub_efi_mmap_iterate (grub_linux_boot_mmap_find, &ctx, 1);
+  if (! ctx.real_mode_target)
+    grub_efi_mmap_iterate (grub_linux_boot_mmap_find, &ctx, 0);
+#else
+  grub_mmap_iterate (grub_linux_boot_mmap_find, &ctx);
+#endif
+  grub_dprintf ("linux", "real_mode_target = %lx, real_size = %x, efi_mmap_size = %x\n",
+                (unsigned long) ctx.real_mode_target,
+               (unsigned) ctx.real_size,
+               (unsigned) efi_mmap_size);
+
+  if (! ctx.real_mode_target)
+    return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate real mode pages");
+
+  {
+    grub_relocator_chunk_t ch;
+    err = grub_relocator_alloc_chunk_addr (relocator, &ch,
+                                          ctx.real_mode_target,
+                                          (ctx.real_size + efi_mmap_size));
+    if (err)
+     return err;
+    real_mode_mem = get_virtual_current_address (ch);
+  }
+  efi_mmap_buf = (grub_uint8_t *) real_mode_mem + ctx.real_size;
+
+  grub_dprintf ("linux", "real_mode_mem = %p\n",
+                real_mode_mem);
+
+  ctx.params = real_mode_mem;
+
+  *ctx.params = linux_params;
+  ctx.params->cmd_line_ptr = ctx.real_mode_target + cl_offset;
+  grub_memcpy ((char *) ctx.params + cl_offset, linux_cmdline,
+              maximal_cmdline_size);
+
+  grub_dprintf ("linux", "code32_start = %x\n",
+               (unsigned) ctx.params->code32_start);
+
+  ctx.e820_num = 0;
+  if (grub_mmap_iterate (grub_linux_boot_mmap_fill, &ctx))
+    return grub_errno;
+  ctx.params->mmap_size = ctx.e820_num;
+
+#ifdef GRUB_MACHINE_EFI
+  {
+    grub_efi_uintn_t efi_desc_size;
+    grub_size_t efi_mmap_target;
+    grub_efi_uint32_t efi_desc_version;
+    err = grub_efi_finish_boot_services (&efi_mmap_size, efi_mmap_buf, NULL,
+                                        &efi_desc_size, &efi_desc_version);
+    if (err)
+      return err;
+    
+    /* Note that no boot services are available from here.  */
+    efi_mmap_target = ctx.real_mode_target 
+      + ((grub_uint8_t *) efi_mmap_buf - (grub_uint8_t *) real_mode_mem);
+    /* Pass EFI parameters.  */
+    if (grub_le_to_cpu16 (ctx.params->version) >= 0x0208)
+      {
+       ctx.params->v0208.efi_mem_desc_size = efi_desc_size;
+       ctx.params->v0208.efi_mem_desc_version = efi_desc_version;
+       ctx.params->v0208.efi_mmap = efi_mmap_target;
+       ctx.params->v0208.efi_mmap_size = efi_mmap_size;
+
+#ifdef __x86_64__
+       ctx.params->v0208.efi_mmap_hi = (efi_mmap_target >> 32);
+#endif
+      }
+    else if (grub_le_to_cpu16 (ctx.params->version) >= 0x0206)
+      {
+       ctx.params->v0206.efi_mem_desc_size = efi_desc_size;
+       ctx.params->v0206.efi_mem_desc_version = efi_desc_version;
+       ctx.params->v0206.efi_mmap = efi_mmap_target;
+       ctx.params->v0206.efi_mmap_size = efi_mmap_size;
+      }
+    else if (grub_le_to_cpu16 (ctx.params->version) >= 0x0204)
+      {
+       ctx.params->v0204.efi_mem_desc_size = efi_desc_size;
+       ctx.params->v0204.efi_mem_desc_version = efi_desc_version;
+       ctx.params->v0204.efi_mmap = efi_mmap_target;
+       ctx.params->v0204.efi_mmap_size = efi_mmap_size;
+      }
+  }
+#endif
+
+  /* FIXME.  */
+  /*  asm volatile ("lidt %0" : : "m" (idt_desc)); */
+  state.ebp = state.edi = state.ebx = 0;
+  state.esi = ctx.real_mode_target;
+  state.esp = ctx.real_mode_target;
+  state.eip = ctx.params->code32_start;
+  return grub_relocator32_boot (relocator, state, 0);
+}
+
+static grub_err_t
+grub_linux_unload (void)
+{
+  grub_dl_unref (my_mod);
+  loaded = 0;
+  grub_free (linux_cmdline);
+  linux_cmdline = 0;
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+               int argc, char *argv[])
+{
+  grub_file_t file = 0;
+  struct linux_i386_kernel_header lh;
+  grub_uint8_t setup_sects;
+  grub_size_t real_size, prot_size, prot_file_size;
+  grub_ssize_t len;
+  int i;
+  grub_size_t align, min_align;
+  int relocatable;
+  grub_uint64_t preferred_address = GRUB_LINUX_BZIMAGE_ADDR;
+
+  grub_dl_ref (my_mod);
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+      goto fail;
+    }
+
+  file = grub_file_open (argv[0], GRUB_FILE_TYPE_LINUX_KERNEL);
+  if (! file)
+    goto fail;
+
+  if (ventoy_linux_argc)
+  {
+      const char *tip = grub_env_get("ventoy_loading_tip");
+      if (tip)
+      {
+          grub_printf("%s\n", tip);
+          grub_refresh();          
+      }
+  }
+
+  if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
+    {
+      if (!grub_errno)
+       grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
+                   argv[0]);
+      goto fail;
+    }
+
+  if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55))
+    {
+      grub_error (GRUB_ERR_BAD_OS, "invalid magic number");
+      goto fail;
+    }
+
+  if (lh.setup_sects > GRUB_LINUX_MAX_SETUP_SECTS)
+    {
+      grub_error (GRUB_ERR_BAD_OS, "too many setup sectors");
+      goto fail;
+    }
+
+  /* FIXME: 2.03 is not always good enough (Linux 2.4 can be 2.03 and
+     still not support 32-bit boot.  */
+  if (lh.header != grub_cpu_to_le32_compile_time (GRUB_LINUX_I386_MAGIC_SIGNATURE)
+      || grub_le_to_cpu16 (lh.version) < 0x0203)
+    {
+      grub_error (GRUB_ERR_BAD_OS, "version too old for 32-bit boot"
+#ifdef GRUB_MACHINE_PCBIOS
+                 " (try with `linux16')"
+#endif
+                 );
+      goto fail;
+    }
+
+  if (! (lh.loadflags & GRUB_LINUX_FLAG_BIG_KERNEL))
+    {
+      grub_error (GRUB_ERR_BAD_OS, "zImage doesn't support 32-bit boot"
+#ifdef GRUB_MACHINE_PCBIOS
+                 " (try with `linux16')"
+#endif
+                 );
+      goto fail;
+    }
+
+  if (grub_le_to_cpu16 (lh.version) >= 0x0206)
+    maximal_cmdline_size = grub_le_to_cpu32 (lh.cmdline_size) + 1;
+  else
+    maximal_cmdline_size = 256;
+
+  if (maximal_cmdline_size < 128)
+    maximal_cmdline_size = 128;
+
+  setup_sects = lh.setup_sects;
+
+  /* If SETUP_SECTS is not set, set it to the default (4).  */
+  if (! setup_sects)
+    setup_sects = GRUB_LINUX_DEFAULT_SETUP_SECTS;
+
+  real_size = setup_sects << GRUB_DISK_SECTOR_BITS;
+  prot_file_size = grub_file_size (file) - real_size - GRUB_DISK_SECTOR_SIZE;
+
+  if (grub_le_to_cpu16 (lh.version) >= 0x205
+      && lh.kernel_alignment != 0
+      && ((lh.kernel_alignment - 1) & lh.kernel_alignment) == 0)
+    {
+      for (align = 0; align < 32; align++)
+       if (grub_le_to_cpu32 (lh.kernel_alignment) & (1 << align))
+         break;
+      relocatable = grub_le_to_cpu32 (lh.relocatable);
+    }
+  else
+    {
+      align = 0;
+      relocatable = 0;
+    }
+    
+  if (grub_le_to_cpu16 (lh.version) >= 0x020a)
+    {
+      min_align = lh.min_alignment;
+      prot_size = grub_le_to_cpu32 (lh.init_size);
+      prot_init_space = page_align (prot_size);
+      if (relocatable)
+       preferred_address = grub_le_to_cpu64 (lh.pref_address);
+      else
+       preferred_address = GRUB_LINUX_BZIMAGE_ADDR;
+    }
+  else
+    {
+      min_align = align;
+      prot_size = prot_file_size;
+      preferred_address = GRUB_LINUX_BZIMAGE_ADDR;
+      /* Usually, the compression ratio is about 50%.  */
+      prot_init_space = page_align (prot_size) * 3;
+    }
+
+  if (allocate_pages (prot_size, &align,
+                     min_align, relocatable,
+                     preferred_address))
+    goto fail;
+
+  grub_memset (&linux_params, 0, sizeof (linux_params));
+  grub_memcpy (&linux_params.setup_sects, &lh.setup_sects, sizeof (lh) - 0x1F1);
+
+  linux_params.code32_start = prot_mode_target + lh.code32_start - GRUB_LINUX_BZIMAGE_ADDR;
+  linux_params.kernel_alignment = (1 << align);
+  linux_params.ps_mouse = linux_params.padding10 =  0;
+
+  /*
+   * The Linux 32-bit boot protocol defines the setup header end
+   * to be at 0x202 + the byte value at 0x201.
+   */
+  len = 0x202 + *((char *) &linux_params.jump + 1);
+
+  /* Verify the struct is big enough so we do not write past the end. */
+  if (len > (char *) &linux_params.edd_mbr_sig_buffer - (char *) &linux_params) {
+    grub_error (GRUB_ERR_BAD_OS, "Linux setup header too big");
+    goto fail;
+  }
+
+  /* We've already read lh so there is no need to read it second time. */
+  len -= sizeof(lh);
+
+  if (grub_file_read (file, (char *) &linux_params + sizeof (lh), len) != len)
+    {
+      if (!grub_errno)
+       grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
+                   argv[0]);
+      goto fail;
+    }
+
+  linux_params.type_of_loader = GRUB_LINUX_BOOT_LOADER_TYPE;
+
+  /* These two are used (instead of cmd_line_ptr) by older versions of Linux,
+     and otherwise ignored.  */
+  linux_params.cl_magic = GRUB_LINUX_CL_MAGIC;
+  linux_params.cl_offset = 0x1000;
+
+  linux_params.ramdisk_image = 0;
+  linux_params.ramdisk_size = 0;
+
+  linux_params.heap_end_ptr = GRUB_LINUX_HEAP_END_OFFSET;
+  linux_params.loadflags |= GRUB_LINUX_FLAG_CAN_USE_HEAP;
+
+  /* These are not needed to be precise, because Linux uses these values
+     only to raise an error when the decompression code cannot find good
+     space.  */
+  linux_params.ext_mem = ((32 * 0x100000) >> 10);
+  linux_params.alt_mem = ((32 * 0x100000) >> 10);
+
+  /* Ignored by Linux.  */
+  linux_params.video_page = 0;
+
+  /* Only used when `video_mode == 0x7', otherwise ignored.  */
+  linux_params.video_ega_bx = 0;
+
+  linux_params.font_size = 16; /* XXX */
+
+#ifdef GRUB_MACHINE_EFI
+#ifdef __x86_64__
+  if (grub_le_to_cpu16 (linux_params.version) < 0x0208 &&
+      ((grub_addr_t) grub_efi_system_table >> 32) != 0)
+    return grub_error(GRUB_ERR_BAD_OS,
+                     "kernel does not support 64-bit addressing");
+#endif
+
+  if (grub_le_to_cpu16 (linux_params.version) >= 0x0208)
+    {
+      linux_params.v0208.efi_signature = GRUB_LINUX_EFI_SIGNATURE;
+      linux_params.v0208.efi_system_table = (grub_uint32_t) (grub_addr_t) grub_efi_system_table;
+#ifdef __x86_64__
+      linux_params.v0208.efi_system_table_hi = (grub_uint32_t) ((grub_uint64_t) grub_efi_system_table >> 32);
+#endif
+    }
+  else if (grub_le_to_cpu16 (linux_params.version) >= 0x0206)
+    {
+      linux_params.v0206.efi_signature = GRUB_LINUX_EFI_SIGNATURE;
+      linux_params.v0206.efi_system_table = (grub_uint32_t) (grub_addr_t) grub_efi_system_table;
+    }
+  else if (grub_le_to_cpu16 (linux_params.version) >= 0x0204)
+    {
+      linux_params.v0204.efi_signature = GRUB_LINUX_EFI_SIGNATURE_0204;
+      linux_params.v0204.efi_system_table = (grub_uint32_t) (grub_addr_t) grub_efi_system_table;
+    }
+#endif
+
+  /* The other parameters are filled when booting.  */
+
+  grub_file_seek (file, real_size + GRUB_DISK_SECTOR_SIZE);
+
+  grub_dprintf ("linux", "bzImage, setup=0x%x, size=0x%x\n",
+               (unsigned) real_size, (unsigned) prot_size);
+
+  /* Look for memory size and video mode specified on the command line.  */
+  linux_mem_size = 0;
+  for (i = 1; i < argc; i++)
+#ifdef GRUB_MACHINE_PCBIOS
+    if (grub_memcmp (argv[i], "vga=", 4) == 0)
+      {
+       /* Video mode selection support.  */
+       char *val = argv[i] + 4;
+       unsigned vid_mode = GRUB_LINUX_VID_MODE_NORMAL;
+       struct grub_vesa_mode_table_entry *linux_mode;
+       grub_err_t err;
+       char *buf;
+
+       grub_dl_load ("vbe");
+
+       if (grub_strcmp (val, "normal") == 0)
+         vid_mode = GRUB_LINUX_VID_MODE_NORMAL;
+       else if (grub_strcmp (val, "ext") == 0)
+         vid_mode = GRUB_LINUX_VID_MODE_EXTENDED;
+       else if (grub_strcmp (val, "ask") == 0)
+         {
+           grub_puts_ (N_("Legacy `ask' parameter no longer supported."));
+
+           /* We usually would never do this in a loader, but "vga=ask" means user
+              requested interaction, so it can't hurt to request keyboard input.  */
+           grub_wait_after_message ();
+
+           goto fail;
+         }
+       else
+         vid_mode = (grub_uint16_t) grub_strtoul (val, 0, 0);
+
+       switch (vid_mode)
+         {
+         case 0:
+         case GRUB_LINUX_VID_MODE_NORMAL:
+           grub_env_set ("gfxpayload", "text");
+           grub_printf_ (N_("%s is deprecated. "
+                            "Use set gfxpayload=%s before "
+                            "linux command instead.\n"),
+                         argv[i], "text");
+           break;
+
+         case 1:
+         case GRUB_LINUX_VID_MODE_EXTENDED:
+           /* FIXME: support 80x50 text. */
+           grub_env_set ("gfxpayload", "text");
+           grub_printf_ (N_("%s is deprecated. "
+                            "Use set gfxpayload=%s before "
+                            "linux command instead.\n"),
+                         argv[i], "text");
+           break;
+         default:
+           /* Ignore invalid values.  */
+           if (vid_mode < GRUB_VESA_MODE_TABLE_START ||
+               vid_mode > GRUB_VESA_MODE_TABLE_END)
+             {
+               grub_env_set ("gfxpayload", "text");
+               /* TRANSLATORS: "x" has to be entered in, like an identifier,
+                  so please don't use better Unicode codepoints.  */
+               grub_printf_ (N_("%s is deprecated. VGA mode %d isn't recognized. "
+                                "Use set gfxpayload=WIDTHxHEIGHT[xDEPTH] "
+                                "before linux command instead.\n"),
+                            argv[i], vid_mode);
+               break;
+             }
+
+           linux_mode = &grub_vesa_mode_table[vid_mode
+                                              - GRUB_VESA_MODE_TABLE_START];
+
+           buf = grub_xasprintf ("%ux%ux%u,%ux%u",
+                                linux_mode->width, linux_mode->height,
+                                linux_mode->depth,
+                                linux_mode->width, linux_mode->height);
+           if (! buf)
+             goto fail;
+
+           grub_printf_ (N_("%s is deprecated. "
+                            "Use set gfxpayload=%s before "
+                            "linux command instead.\n"),
+                        argv[i], buf);
+           err = grub_env_set ("gfxpayload", buf);
+           grub_free (buf);
+           if (err)
+             goto fail;
+         }
+      }
+    else
+#endif /* GRUB_MACHINE_PCBIOS */
+    if (grub_memcmp (argv[i], "mem=", 4) == 0)
+      {
+       char *val = argv[i] + 4;
+
+       linux_mem_size = grub_strtoul (val, &val, 0);
+
+       if (grub_errno)
+         {
+           grub_errno = GRUB_ERR_NONE;
+           linux_mem_size = 0;
+         }
+       else
+         {
+           int shift = 0;
+
+           switch (grub_tolower (val[0]))
+             {
+             case 'g':
+               shift += 10;
+               /* FALLTHROUGH */
+             case 'm':
+               shift += 10;
+               /* FALLTHROUGH */
+             case 'k':
+               shift += 10;
+               /* FALLTHROUGH */
+             default:
+               break;
+             }
+
+           /* Check an overflow.  */
+           if (linux_mem_size > (~0UL >> shift))
+             linux_mem_size = 0;
+           else
+             linux_mem_size <<= shift;
+         }
+      }
+    else if (grub_memcmp (argv[i], "quiet", sizeof ("quiet") - 1) == 0)
+      {
+       linux_params.loadflags |= GRUB_LINUX_FLAG_QUIET;
+      }
+
+  /* Create kernel command line.  */
+  linux_cmdline = grub_zalloc (maximal_cmdline_size + 1);
+  if (!linux_cmdline)
+    goto fail;
+  grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE));
+  {
+    grub_err_t err;
+
+    if (ventoy_linux_argc)
+    {
+        ventoy_bootopt_hook(argc, argv);
+        err = grub_create_loader_cmdline (ventoy_linux_argc, ventoy_linux_args,
+                                     linux_cmdline
+                                     + sizeof (LINUX_IMAGE) - 1,
+                                     maximal_cmdline_size
+                                     - (sizeof (LINUX_IMAGE) - 1),
+                                     GRUB_VERIFY_KERNEL_CMDLINE);
+    }
+    else
+    {
+        err = grub_create_loader_cmdline (argc, argv,
+                                     linux_cmdline
+                                     + sizeof (LINUX_IMAGE) - 1,
+                                     maximal_cmdline_size
+                                     - (sizeof (LINUX_IMAGE) - 1),
+                                     GRUB_VERIFY_KERNEL_CMDLINE);
+    }
+    
+    if (err)
+      goto fail;
+  }
+
+  len = prot_file_size;
+  if (grub_file_read (file, prot_mode_mem, len) != len && !grub_errno)
+    grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
+               argv[0]);
+
+  if (grub_errno == GRUB_ERR_NONE)
+    {
+      grub_loader_set (grub_linux_boot, grub_linux_unload,
+                      0 /* set noreturn=0 in order to avoid grub_console_fini() */);
+      loaded = 1;
+    }
+
+ fail:
+
+  if (file)
+    grub_file_close (file);
+
+  if (grub_errno != GRUB_ERR_NONE)
+    {
+      grub_dl_unref (my_mod);
+      loaded = 0;
+    }
+
+  return grub_errno;
+}
+
+static grub_err_t
+grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+                int argc, char *argv[])
+{
+  grub_size_t size = 0, aligned_size = 0;
+  grub_addr_t addr_min, addr_max;
+  grub_addr_t addr;
+  grub_err_t err;
+  struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 };
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+      goto fail;
+    }
+
+  if (! loaded)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first"));
+      goto fail;
+    }
+
+  if (grub_initrd_init (argc, argv, &initrd_ctx))
+    goto fail;
+
+  size = grub_get_initrd_size (&initrd_ctx);
+  aligned_size = ALIGN_UP (size, 4096);
+
+  /* Get the highest address available for the initrd.  */
+  if (grub_le_to_cpu16 (linux_params.version) >= 0x0203)
+    {
+      addr_max = grub_cpu_to_le32 (linux_params.initrd_addr_max);
+
+      /* XXX in reality, Linux specifies a bogus value, so
+        it is necessary to make sure that ADDR_MAX does not exceed
+        0x3fffffff.  */
+      if (addr_max > GRUB_LINUX_INITRD_MAX_ADDRESS)
+       addr_max = GRUB_LINUX_INITRD_MAX_ADDRESS;
+    }
+  else
+    addr_max = GRUB_LINUX_INITRD_MAX_ADDRESS;
+
+  if (linux_mem_size != 0 && linux_mem_size < addr_max)
+    addr_max = linux_mem_size;
+
+  /* Linux 2.3.xx has a bug in the memory range check, so avoid
+     the last page.
+     Linux 2.2.xx has a bug in the memory range check, which is
+     worse than that of Linux 2.3.xx, so avoid the last 64kb.  */
+  addr_max -= 0x10000;
+
+  addr_min = (grub_addr_t) prot_mode_target + prot_init_space;
+
+  /* Put the initrd as high as possible, 4KiB aligned.  */
+  addr = (addr_max - aligned_size) & ~0xFFF;
+
+  if (addr < addr_min)
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, "the initrd is too big");
+      goto fail;
+    }
+
+  {
+    grub_relocator_chunk_t ch;
+    err = grub_relocator_alloc_chunk_align (relocator, &ch,
+                                           addr_min, addr, aligned_size,
+                                           0x1000,
+                                           GRUB_RELOCATOR_PREFERENCE_HIGH,
+                                           1);
+    if (err)
+      return err;
+    initrd_mem = get_virtual_current_address (ch);
+    initrd_mem_target = get_physical_target_address (ch);
+  }
+
+  if (grub_initrd_load (&initrd_ctx, argv, initrd_mem))
+    goto fail;
+
+  grub_dprintf ("linux", "Initrd, addr=0x%x, size=0x%x\n",
+               (unsigned) addr, (unsigned) size);
+
+  linux_params.ramdisk_image = initrd_mem_target;
+  linux_params.ramdisk_size = size;
+  linux_params.root_dev = 0x0100; /* XXX */
+
+ fail:
+  grub_initrd_close (&initrd_ctx);
+
+  return grub_errno;
+}
+
+static grub_err_t
+ventoy_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+                int argc, char *argv[])
+{
+    int i;
+    char buf[64];
+    char *newargv[32] = {NULL};
+
+    if (ventoy_debug) grub_printf("ventoy_cmd_initrd %d\n", ventoy_linux_argc);
+
+    if (ventoy_linux_argc == 0)
+    {
+        return grub_cmd_initrd(cmd, argc, argv);        
+    }
+
+    grub_snprintf(buf, sizeof(buf), "mem:%s:size:%s", grub_env_get("ventoy_cpio_addr"), grub_env_get("ventoy_cpio_size"));
+
+    if (ventoy_debug) grub_printf("membuf=%s\n", buf);
+
+    newargv[0] = buf;
+    for (i = 0; i < argc; i++)
+    {
+        newargv[i + 1] = argv[i];
+    }
+
+    ventoy_initrd_called = 1;
+    
+    return grub_cmd_initrd(cmd, argc + 1, newargv);
+}
+
+
+static grub_command_t cmd_linux, cmd_initrd, cmd_linuxefi, cmd_initrdefi, cmd_set_bootopt, cmd_unset_bootopt;
+
+GRUB_MOD_INIT(linux)
+{
+  cmd_linux = grub_register_command ("linux", grub_cmd_linux,
+                                    0, N_("Load Linux."));
+  cmd_initrd = grub_register_command ("initrd", ventoy_cmd_initrd,
+                                     0, N_("Load initrd."));
+
+  cmd_linuxefi = grub_register_command ("linuxefi", grub_cmd_linux,
+                                    0, N_("Load Linux."));
+  cmd_initrdefi = grub_register_command ("initrdefi", ventoy_cmd_initrd,
+                                     0, N_("Load initrd."));
+  cmd_set_bootopt = grub_register_command ("vt_set_boot_opt", grub_cmd_set_boot_opt, 0, N_("set ext boot opt"));
+  cmd_unset_bootopt = grub_register_command ("vt_unset_boot_opt", grub_cmd_unset_boot_opt, 0, N_("unset ext boot opt"));
+
+  ventoy_linux_args = grub_zalloc(sizeof(char *) * LINUX_MAX_ARGC);
+
+  my_mod = mod;
+}
+
+GRUB_MOD_FINI(linux)
+{
+  grub_unregister_command (cmd_linux);
+  grub_unregister_command (cmd_initrd);
+}
diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/normal/main.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/normal/main.c
new file mode 100644 (file)
index 0000000..bc29d3b
--- /dev/null
@@ -0,0 +1,575 @@
+/* main.c - the normal mode main routine */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2000,2001,2002,2003,2005,2006,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/kernel.h>
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/menu.h>
+#include <grub/misc.h>
+#include <grub/file.h>
+#include <grub/mm.h>
+#include <grub/term.h>
+#include <grub/env.h>
+#include <grub/parser.h>
+#include <grub/reader.h>
+#include <grub/menu_viewer.h>
+#include <grub/auth.h>
+#include <grub/i18n.h>
+#include <grub/charset.h>
+#include <grub/script_sh.h>
+#include <grub/bufio.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+#define GRUB_DEFAULT_HISTORY_SIZE      50
+
+static int nested_level = 0;
+int grub_normal_exit_level = 0;
+
+void
+grub_normal_free_menu (grub_menu_t menu)
+{
+  grub_menu_entry_t entry = menu->entry_list;
+
+  while (entry)
+    {
+      grub_menu_entry_t next_entry = entry->next;
+      grub_size_t i;
+
+      if (entry->classes)
+       {
+         struct grub_menu_entry_class *class;
+         for (class = entry->classes; class; class = class->next)
+           grub_free (class->name);
+         grub_free (entry->classes);
+       }
+
+      if (entry->args)
+       {
+         for (i = 0; entry->args[i]; i++)
+           grub_free (entry->args[i]);
+         grub_free (entry->args);
+       }
+
+      if (entry->bls)
+       {
+         entry->bls->visible = 0;
+       }
+
+      grub_free ((void *) entry->id);
+      grub_free ((void *) entry->users);
+      grub_free ((void *) entry->title);
+      grub_free ((void *) entry->sourcecode);
+      grub_free (entry);
+      entry = next_entry;
+    }
+
+  grub_free (menu);
+  grub_env_unset_menu ();
+}
+
+/* Helper for read_config_file.  */
+static grub_err_t
+read_config_file_getline (char **line, int cont __attribute__ ((unused)),
+                         void *data)
+{
+  grub_file_t file = data;
+
+  while (1)
+    {
+      char *buf;
+
+      *line = buf = grub_file_getline (file);
+      if (! buf)
+       return grub_errno;
+
+      if (buf[0] == '#')
+       grub_free (*line);
+      else
+       break;
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_menu_t
+read_config_file (const char *config)
+{
+  grub_file_t rawfile, file;
+  char *old_file = 0, *old_dir = 0;
+  char *config_dir, *ptr = 0;
+  const char *ctmp;
+
+  grub_menu_t newmenu;
+
+  newmenu = grub_env_get_menu ();
+  if (! newmenu)
+    {
+      newmenu = grub_zalloc (sizeof (*newmenu));
+      if (! newmenu)
+       return 0;
+
+      grub_env_set_menu (newmenu);
+    }
+
+  /* Try to open the config file.  */
+  rawfile = grub_file_open (config, GRUB_FILE_TYPE_CONFIG);
+  if (! rawfile)
+    return 0;
+
+  file = grub_bufio_open (rawfile, 0);
+  if (! file)
+    {
+      grub_file_close (rawfile);
+      return 0;
+    }
+
+  ctmp = grub_env_get ("config_file");
+  if (ctmp)
+    old_file = grub_strdup (ctmp);
+  ctmp = grub_env_get ("config_directory");
+  if (ctmp)
+    old_dir = grub_strdup (ctmp);
+  if (*config == '(')
+    {
+      grub_env_set ("config_file", config);
+      config_dir = grub_strdup (config);
+    }
+  else
+    {
+      /* $root is guranteed to be defined, otherwise open above would fail */
+      config_dir = grub_xasprintf ("(%s)%s", grub_env_get ("root"), config);
+      if (config_dir)
+       grub_env_set ("config_file", config_dir);
+    }
+  if (config_dir)
+    {
+      ptr = grub_strrchr (config_dir, '/');
+      if (ptr)
+       *ptr = 0;
+      grub_env_set ("config_directory", config_dir);
+      grub_free (config_dir);
+    }
+
+  grub_env_export ("config_file");
+  grub_env_export ("config_directory");
+
+  while (1)
+    {
+      char *line;
+
+      /* Print an error, if any.  */
+      grub_print_error ();
+      grub_errno = GRUB_ERR_NONE;
+
+      if ((read_config_file_getline (&line, 0, file)) || (! line))
+       break;
+
+      grub_normal_parse_line (line, read_config_file_getline, file);
+      grub_free (line);
+    }
+
+  if (old_file)
+    grub_env_set ("config_file", old_file);
+  else
+    grub_env_unset ("config_file");
+  if (old_dir)
+    grub_env_set ("config_directory", old_dir);
+  else
+    grub_env_unset ("config_directory");
+  grub_free (old_file);
+  grub_free (old_dir);
+
+  grub_file_close (file);
+
+  return newmenu;
+}
+
+/* Initialize the screen.  */
+void
+grub_normal_init_page (struct grub_term_output *term,
+                      int y)
+{
+  grub_ssize_t msg_len;
+  int posx;
+  char *msg_formatted;
+  grub_uint32_t *unicode_msg;
+  grub_uint32_t *last_position;
+  grub_term_cls (term);
+
+  msg_formatted = grub_xasprintf (_("GNU GRUB  version %s"), PACKAGE_VERSION);
+  if (!msg_formatted)
+    return;
+  msg_len = grub_utf8_to_ucs4_alloc (msg_formatted,
+                                    &unicode_msg, &last_position);
+  grub_free (msg_formatted);
+  if (msg_len < 0)
+    {
+      return;
+    }
+
+  posx = grub_getstringwidth (unicode_msg, last_position, term);
+  posx = ((int) grub_term_width (term) - posx) / 2;
+  if (posx < 0)
+    posx = 0;
+  grub_term_gotoxy (term, (struct grub_term_coordinate) { posx, y });
+
+  grub_print_ucs4 (unicode_msg, last_position, 0, 0, term);
+  grub_putcode ('\n', term);
+  grub_putcode ('\n', term);
+  grub_free (unicode_msg);
+}
+
+static void
+read_lists (const char *val)
+{
+  if (! grub_no_modules)
+    {
+      read_command_list (val);
+      read_fs_list (val);
+      read_crypto_list (val);
+      read_terminal_list (val);
+    }
+  grub_gettext_reread_prefix (val);
+}
+
+static char *
+read_lists_hook (struct grub_env_var *var __attribute__ ((unused)),
+                const char *val)
+{
+  read_lists (val);
+  return val ? grub_strdup (val) : NULL;
+}
+
+/* Read the config file CONFIG and execute the menu interface or
+   the command line interface if BATCH is false.  */
+void
+grub_normal_execute (const char *config, int nested, int batch)
+{
+  grub_menu_t menu = 0;
+  const char *prefix;
+
+  if (! nested)
+    {
+      prefix = grub_env_get ("prefix");
+      read_lists (prefix);
+      grub_register_variable_hook ("prefix", NULL, read_lists_hook);
+    }
+
+  grub_boot_time ("Executing config file");
+
+  if (config)
+    {
+      menu = read_config_file (config);
+
+      /* Ignore any error.  */
+      grub_errno = GRUB_ERR_NONE;
+    }
+
+  grub_boot_time ("Executed config file");
+
+  if (! batch)
+    {
+      if (menu && menu->size)
+       {
+
+         grub_boot_time ("Entering menu");
+         grub_show_menu (menu, nested, 0);
+         if (nested)
+           grub_normal_free_menu (menu);
+       }
+    }
+}
+
+/* This starts the normal mode.  */
+void
+grub_enter_normal_mode (const char *config)
+{
+  grub_boot_time ("Entering normal mode");
+  nested_level++;
+  grub_normal_execute (config, 0, 0);
+  grub_boot_time ("Entering shell");
+  grub_cmdline_run (0, 1);
+  nested_level--;
+  if (grub_normal_exit_level)
+    grub_normal_exit_level--;
+  grub_boot_time ("Exiting normal mode");
+}
+
+/* Enter normal mode from rescue mode.  */
+static grub_err_t
+grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)),
+                int argc, char *argv[])
+{
+  if (argc == 0)
+    {
+      /* Guess the config filename. It is necessary to make CONFIG static,
+        so that it won't get broken by longjmp.  */
+      char *config;
+      const char *prefix;
+
+      prefix = grub_env_get ("prefix");
+      if (prefix)
+       {
+         config = grub_xasprintf ("%s/grub.cfg", prefix);
+         if (! config)
+           goto quit;
+
+         grub_enter_normal_mode (config);
+         grub_free (config);
+       }
+      else
+       grub_enter_normal_mode (0);
+    }
+  else
+    grub_enter_normal_mode (argv[0]);
+
+quit:
+  return 0;
+}
+
+/* Exit from normal mode to rescue mode.  */
+static grub_err_t
+grub_cmd_normal_exit (struct grub_command *cmd __attribute__ ((unused)),
+                     int argc __attribute__ ((unused)),
+                     char *argv[] __attribute__ ((unused)))
+{
+  if (nested_level <= grub_normal_exit_level)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "not in normal environment");
+  grub_normal_exit_level++;
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_normal_reader_init (int nested)
+{
+  struct grub_term_output *term;
+  const char *msg_esc = _("ESC at any time exits.");
+  char *msg_formatted;
+
+  msg_formatted = grub_xasprintf (_("Minimal BASH-like line editing is supported. For "
+                                   "the first word, TAB lists possible command completions. Anywhere "
+                                   "else TAB lists possible device or file completions. %s"),
+                                 nested ? msg_esc : "");
+  if (!msg_formatted)
+    return grub_errno;
+
+  FOR_ACTIVE_TERM_OUTPUTS(term)
+  {
+    grub_normal_init_page (term, 1);
+    grub_term_setcursor (term, 1);
+
+    if (grub_term_width (term) > 3 + STANDARD_MARGIN + 20)
+      grub_print_message_indented (msg_formatted, 3, STANDARD_MARGIN, term);
+    else
+      grub_print_message_indented (msg_formatted, 0, 0, term);
+    grub_putcode ('\n', term);
+    grub_putcode ('\n', term);
+    grub_putcode ('\n', term);
+  }
+  grub_free (msg_formatted);
+  return 0;
+}
+
+static grub_err_t
+grub_normal_read_line_real (char **line, int cont, int nested)
+{
+  const char *prompt;
+
+  if (cont)
+    /* TRANSLATORS: it's command line prompt.  */
+    prompt = _(">");
+  else
+    /* TRANSLATORS: it's command line prompt.  */
+    prompt = _("grub>");
+
+  if (!prompt)
+    return grub_errno;
+
+  while (1)
+    {
+      *line = grub_cmdline_get (prompt);
+      if (*line)
+       return 0;
+
+      if (cont || nested)
+       {
+         grub_free (*line);
+         *line = 0;
+         return grub_errno;
+       }
+    }
+}
+
+static grub_err_t
+grub_normal_read_line (char **line, int cont,
+                      void *data __attribute__ ((unused)))
+{
+  return grub_normal_read_line_real (line, cont, 0);
+}
+
+void
+grub_cmdline_run (int nested, int force_auth)
+{
+  grub_err_t err = GRUB_ERR_NONE;
+
+  do
+    {
+      err = grub_auth_check_authentication (NULL);
+    }
+  while (err && force_auth);
+
+  if (err)
+    {
+      grub_print_error ();
+      grub_errno = GRUB_ERR_NONE;
+      return;
+    }
+
+  grub_normal_reader_init (nested);
+
+  while (1)
+    {
+      char *line = NULL;
+
+      if (grub_normal_exit_level)
+       break;
+
+      /* Print an error, if any.  */
+      grub_print_error ();
+      grub_errno = GRUB_ERR_NONE;
+
+      grub_normal_read_line_real (&line, 0, nested);
+      if (! line)
+       break;
+
+      grub_normal_parse_line (line, grub_normal_read_line, NULL);
+      grub_free (line);
+    }
+}
+
+static char *
+grub_env_write_pager (struct grub_env_var *var __attribute__ ((unused)),
+                     const char *val)
+{
+  grub_set_more ((*val == '1'));
+  return grub_strdup (val);
+}
+
+/* clear */
+static grub_err_t
+grub_mini_cmd_clear (struct grub_command *cmd __attribute__ ((unused)),
+                  int argc __attribute__ ((unused)),
+                  char *argv[] __attribute__ ((unused)))
+{
+  grub_cls ();
+  return 0;
+}
+
+static grub_command_t cmd_clear;
+
+static void (*grub_xputs_saved) (const char *str);
+static const char *features[] = {
+  "feature_chainloader_bpb", "feature_ntldr", "feature_platform_search_hint",
+  "feature_default_font_path", "feature_all_video_module",
+  "feature_menuentry_id", "feature_menuentry_options", "feature_200_final",
+  "feature_nativedisk_cmd", "feature_timeout_style"
+};
+
+GRUB_MOD_INIT(normal)
+{
+  unsigned i;
+
+  grub_boot_time ("Preparing normal module");
+
+  /* Previously many modules depended on gzio. Be nice to user and load it.  */
+  grub_dl_load ("gzio");
+  grub_errno = 0;
+
+  grub_normal_auth_init ();
+  grub_context_init ();
+  grub_script_init ();
+  grub_menu_init ();
+
+  grub_xputs_saved = grub_xputs;
+  grub_xputs = grub_xputs_normal;
+
+  /* Normal mode shouldn't be unloaded.  */
+  if (mod)
+    grub_dl_ref (mod);
+
+  cmd_clear =
+    grub_register_command ("clear", grub_mini_cmd_clear,
+                          0, N_("Clear the screen."));
+
+  grub_set_history (GRUB_DEFAULT_HISTORY_SIZE);
+
+  grub_register_variable_hook ("pager", 0, grub_env_write_pager);
+  grub_env_export ("pager");
+
+  /* Register a command "normal" for the rescue mode.  */
+  grub_register_command ("normal", grub_cmd_normal,
+                        0, N_("Enter normal mode."));
+  grub_register_command ("normal_exit", grub_cmd_normal_exit,
+                        0, N_("Exit from normal mode."));
+
+  /* Reload terminal colors when these variables are written to.  */
+  grub_register_variable_hook ("color_normal", NULL, grub_env_write_color_normal);
+  grub_register_variable_hook ("color_highlight", NULL, grub_env_write_color_highlight);
+
+  /* Preserve hooks after context changes.  */
+  grub_env_export ("color_normal");
+  grub_env_export ("color_highlight");
+
+  /* Set default color names.  */
+  grub_env_set ("color_normal", "light-gray/black");
+  grub_env_set ("color_highlight", "black/light-gray");
+
+  for (i = 0; i < ARRAY_SIZE (features); i++)
+    {
+      grub_env_set (features[i], "y");
+      grub_env_export (features[i]);
+    }
+  grub_env_set ("grub_cpu", GRUB_TARGET_CPU);
+  grub_env_export ("grub_cpu");
+  grub_env_set ("grub_platform", GRUB_PLATFORM);
+  grub_env_export ("grub_platform");
+
+  grub_boot_time ("Normal module prepared");
+}
+
+GRUB_MOD_FINI(normal)
+{
+  grub_context_fini ();
+  grub_script_fini ();
+  grub_menu_fini ();
+  grub_normal_auth_fini ();
+
+  grub_xputs = grub_xputs_saved;
+
+  grub_set_history (0);
+  grub_register_variable_hook ("pager", 0, 0);
+  grub_fs_autoload_hook = 0;
+  grub_unregister_command (cmd_clear);
+}
index e5d8b88cac78bf15cefe4607ebbf0a41539e1781..070f6d20fe4d23b06cae25a11901c1f910666632 100644 (file)
@@ -803,6 +803,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
              goto refresh;
 
         case GRUB_TERM_KEY_F2:
+        case '2':
             if (0 == g_ventoy_fn_mutex) {
                 cmdstr = grub_env_get("VTOY_F2_CMD");
                 if (cmdstr)
@@ -816,6 +817,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
             }
             break;
         case GRUB_TERM_KEY_F3:
+        case '3':
             if (0 == g_ventoy_fn_mutex) {
                 cmdstr = grub_env_get("VTOY_F3_CMD");
                 if (cmdstr)
@@ -827,6 +829,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
             }
             break;
         case GRUB_TERM_KEY_F4:
+        case '4':
             if (0 == g_ventoy_fn_mutex) {
                 cmdstr = grub_env_get("VTOY_F4_CMD");
                 if (cmdstr)
@@ -840,6 +843,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
             }
             break;
         case GRUB_TERM_KEY_F5:
+        case '5':
             if (0 == g_ventoy_fn_mutex) {
                 cmdstr = grub_env_get("VTOY_F5_CMD");
                 if (cmdstr)
@@ -853,6 +857,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
             }
             break;
         case GRUB_TERM_KEY_F6:
+        case '6':
             if (0 == g_ventoy_fn_mutex) {
                 cmdstr = grub_env_get("VTOY_F6_CMD");
                 if (cmdstr)
@@ -866,6 +871,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
             }
             break;
         case GRUB_TERM_KEY_F7:
+        case '7':
             cmdstr = grub_env_get("VTOY_F7_CMD");
             if (cmdstr)
             {
@@ -875,6 +881,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
             }
             break;
         case GRUB_TERM_KEY_F1:
+        case '1':
             menu_fini ();
             g_ventoy_memdisk_mode = 1 - g_ventoy_memdisk_mode;
             g_ventoy_menu_refresh = 1;
index cb1d3d61e4ab163acfe8c4754aedfdcd5938932d..cd96ceb181f259116c40900b58f5b205743b91cb 100644 (file)
@@ -180,11 +180,13 @@ command-line or ESC to discard edits and return to the GRUB menu."),
 
       if (nested)
        {
+      #if 0
          ret += grub_print_message_indented_real
            (_("Press enter to boot the selected OS, "
               "`e' to edit the commands before booting "
               "or `c' for a command-line. ESC to return previous menu."),
             STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
+      #endif
        }
       else
        {
@@ -195,7 +197,7 @@ command-line or ESC to discard edits and return to the GRUB menu."),
       
          ret += grub_print_message_indented_real("\n", STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
          ret += grub_print_message_indented_real(grub_env_get("VTOY_HOTKEY_TIP"),
-            STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
+            3, 6, term, dry_run);
        }       
     }
   return ret;
index 2995bd30e6a5418a6e8cefbd5057ccd88031c5fd..e10751f9d3ae86b60fa4f67de5f4146514374b9d 100644 (file)
@@ -34,6 +34,7 @@
 #include <grub/i18n.h>
 #include <grub/net.h>
 #include <grub/misc.h>
+#include <grub/kernel.h>
 #ifdef GRUB_MACHINE_EFI
 #include <grub/efi/efi.h>
 #endif
@@ -317,6 +318,38 @@ static grub_err_t ventoy_cmd_strstr(grub_extcmd_context_t ctxt, int argc, char *
     return (grub_strstr(args[0], args[1])) ? 0 : 1;
 }
 
+static grub_err_t ventoy_cmd_strbegin(grub_extcmd_context_t ctxt, int argc, char **args)
+{
+    char *c0, *c1;
+    
+    (void)ctxt;
+
+    if (argc != 2)
+    {
+        return 1;
+    }
+
+    c0 = args[0];
+    c1 = args[1];
+
+    while (*c0 && *c1)
+    {
+        if (*c0 != *c1)
+        {
+            return 1;
+        }
+        c0++;
+        c1++;
+    }
+
+    if (*c1)
+    {
+        return 1;
+    }
+
+    return 0;
+}
+
 static grub_err_t ventoy_cmd_incr(grub_extcmd_context_t ctxt, int argc, char **args)
 {
     long value_long = 0;
@@ -410,7 +443,122 @@ static grub_err_t ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt, int argc,
     return 0;
 }
 
-static grub_err_t ventoy_cmd_load_iso_to_mem(grub_extcmd_context_t ctxt, int argc, char **args)
+static int ventoy_load_efiboot_template(char **buf, int *datalen, int *direntoff)
+{
+    int len;
+    grub_file_t file;
+    char exec[128];
+    char *data = NULL;
+    grub_uint32_t offset;
+
+    file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
+    if (file == NULL)
+    {
+        debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
+        return 1;
+    }
+
+    len = (int)file->size;
+    
+    data = (char *)grub_malloc(file->size);
+    if (!data)
+    {
+        return 1;
+    }
+    
+    grub_file_read(file, data, file->size);
+    grub_file_close(file); 
+
+    grub_snprintf(exec, sizeof(exec), "loopback efiboot mem:0x%llx:size:%d", (ulonglong)(ulong)data, len);
+    grub_script_execute_sourcecode(exec);
+
+    file = grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD);    
+    offset = (grub_uint32_t)grub_iso9660_get_last_file_dirent_pos(file);
+    grub_file_close(file);
+    
+    grub_script_execute_sourcecode("loopback -d efiboot");
+
+    *buf = data;
+    *datalen = len;
+    *direntoff = offset + 2;
+
+    return 0;
+}
+
+static grub_err_t ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt, int argc, char **args)
+{
+    int len = 0;
+    int totlen = 0;
+    int offset = 0;
+    grub_file_t file;
+    char name[32];
+    char value[32];
+    char *buf = NULL;
+    char *data = NULL;
+    ventoy_iso9660_override *dirent;
+    
+    (void)ctxt;
+
+    if (argc != 2)
+    {
+        return 1;
+    }
+
+    totlen = sizeof(ventoy_chain_head);
+
+    if (ventoy_load_efiboot_template(&buf, &len, &offset))
+    {
+        debug("failed to load efiboot template %d\n", len);
+        return 1;
+    }
+
+    totlen += len;
+    
+    debug("efiboot template len:%d offset:%d\n", len, offset);
+
+    file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s", args[0]);
+    if (file == NULL)
+    {
+        debug("failed to open file <%s>\n", args[0]);
+        return 1;
+    }
+
+    totlen += ventoy_align_2k(file->size);
+
+    dirent = (ventoy_iso9660_override *)(buf + offset);
+    dirent->first_sector = len / 2048;
+    dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector);
+    dirent->size = (grub_uint32_t)file->size;
+    dirent->size_be = grub_swap_bytes32(dirent->size);
+
+    debug("rawiso len:%d efilen:%d total:%d\n", len, (int)file->size, totlen);
+
+#ifdef GRUB_MACHINE_EFI
+    data = (char *)grub_efi_allocate_iso_buf(totlen);
+#else
+    data = (char *)grub_malloc(totlen);
+#endif   
+
+    ventoy_fill_os_param(file, (ventoy_os_param *)data);
+
+    grub_memcpy(data + sizeof(ventoy_chain_head), buf, len);
+    grub_check_free(buf);
+
+    grub_file_read(file, data + sizeof(ventoy_chain_head) + len, file->size);
+    grub_file_close(file); 
+
+    grub_snprintf(name, sizeof(name), "%s_addr", args[1]);
+    grub_snprintf(value, sizeof(value), "0x%llx", (ulonglong)(ulong)data);
+    grub_env_set(name, value);
+    
+    grub_snprintf(name, sizeof(name), "%s_size", args[1]);
+    grub_snprintf(value, sizeof(value), "%d", (int)(totlen));
+    grub_env_set(name, value);
+
+    return 0;
+}
+
+static grub_err_t ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt, int argc, char **args)
 {
     int rc = 1;
     char name[32];
@@ -430,7 +578,7 @@ static grub_err_t ventoy_cmd_load_iso_to_mem(grub_extcmd_context_t ctxt, int arg
     file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
     if (file == NULL)
     {
-        debug("failed to open file <%s> for udf check\n", args[0]);
+        debug("failed to open file <%s>\n", args[0]);
         return 1;
     }
 
@@ -456,6 +604,57 @@ static grub_err_t ventoy_cmd_load_iso_to_mem(grub_extcmd_context_t ctxt, int arg
     return rc;
 }
 
+static grub_err_t ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt, int argc, char **args)
+{
+    int rc = 1;
+    int headlen;
+    char name[32];
+    char value[32];
+    char *buf = NULL;
+    grub_file_t file;
+    
+    (void)ctxt;
+    (void)argc;
+    (void)args;
+
+    if (argc != 2)
+    {
+        return rc;
+    }
+
+    file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
+    if (file == NULL)
+    {
+        debug("failed to open file <%s> for udf check\n", args[0]);
+        return 1;
+    }
+
+    headlen = sizeof(ventoy_chain_head);
+
+#ifdef GRUB_MACHINE_EFI
+    buf = (char *)grub_efi_allocate_iso_buf(headlen + file->size);
+#else
+    buf = (char *)grub_malloc(headlen + file->size);
+#endif   
+
+    ventoy_fill_os_param(file, (ventoy_os_param *)buf);
+
+    grub_file_read(file, buf + headlen, file->size);
+
+    grub_snprintf(name, sizeof(name), "%s_addr", args[1]);
+    grub_snprintf(value, sizeof(value), "0x%llx", (unsigned long long)(unsigned long)buf);
+    grub_env_set(name, value);
+    
+    grub_snprintf(name, sizeof(name), "%s_size", args[1]);
+    grub_snprintf(value, sizeof(value), "%llu", (unsigned long long)file->size);
+    grub_env_set(name, value);
+
+    grub_file_close(file); 
+    rc = 0;
+    
+    return rc;
+}
+
 static grub_err_t ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt, int argc, char **args)
 {
     (void)ctxt;
@@ -834,6 +1033,14 @@ static int ventoy_colect_img_files(const char *filename, const struct grub_dirho
             type = img_type_efi;
         }
         #endif
+        else if (0 == grub_strcasecmp(filename + len - 4, ".img"))
+        {
+            if (len == 18 && grub_strncmp(filename, "ventoy_wimboot", 14) == 0)
+            {
+                return 0;
+            }
+            type = img_type_img;
+        }
         else
         {
             return 0;
@@ -1359,13 +1566,14 @@ static grub_err_t ventoy_cmd_img_name(grub_extcmd_context_t ctxt, int argc, char
 static grub_err_t ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt, int argc, char **args)
 {
     int img_id = 0;
+    char value[32];
     char *pos = NULL;
     const char *id = NULL;
     img_info *cur = g_ventoy_img_list;
 
     (void)ctxt;
     
-    if (argc != 1)
+    if (argc < 1 || argc > 2)
     {
         return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {var}", cmd_raw_name);
     }
@@ -1398,6 +1606,12 @@ static grub_err_t ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt, int arg
 
     grub_env_set(args[0], cur->path);
 
+    if (argc > 1)
+    {
+        grub_snprintf(value, sizeof(value), "%llu", (ulonglong)(cur->size));
+        grub_env_set(args[1], value);        
+    }
+
     VENTOY_CMD_RETURN(GRUB_ERR_NONE);
 }
 
@@ -2366,6 +2580,28 @@ end:
     return 0;
 }
 
+static grub_err_t ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt, int argc, char **args)
+{
+    (void)ctxt;
+    (void)argc;
+    (void)args;
+
+    ventoy_env_hook_root(1);
+    
+    return 0;
+}
+
+static grub_err_t ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt, int argc, char **args)
+{
+    (void)ctxt;
+    (void)argc;
+    (void)args;
+
+    ventoy_env_hook_root(0);
+    
+    return 0;
+}
+
 grub_uint64_t ventoy_grub_get_file_size(const char *fmt, ...)
 {
     grub_uint64_t size = 0;
@@ -2489,6 +2725,7 @@ static cmd_para ventoy_cmds[] =
 {
     { "vt_incr",  ventoy_cmd_incr,  0, NULL, "{Var} {INT}",   "Increase integer variable",    NULL },
     { "vt_strstr",  ventoy_cmd_strstr,  0, NULL, "",   "",    NULL },
+    { "vt_str_begin",  ventoy_cmd_strbegin,  0, NULL, "",   "",    NULL },
     { "vt_debug", ventoy_cmd_debug, 0, NULL, "{on|off}",   "turn debug on/off",    NULL },
     { "vtdebug", ventoy_cmd_debug, 0, NULL, "{on|off}",   "turn debug on/off",    NULL },
     { "vtbreak", ventoy_cmd_break, 0, NULL, "{level}",   "set debug break",    NULL },
@@ -2502,7 +2739,10 @@ static cmd_para ventoy_cmds[] =
     { "vt_img_sector", ventoy_cmd_img_sector, 0, NULL, "{imageName}", "", NULL },
     { "vt_dump_img_sector", ventoy_cmd_dump_img_sector, 0, NULL, "", "", NULL },
     { "vt_load_wimboot", ventoy_cmd_load_wimboot, 0, NULL, "", "", NULL },
+
     { "vt_load_cpio", ventoy_cmd_load_cpio, 0, NULL, "", "", NULL },
+    { "vt_trailer_cpio", ventoy_cmd_trailer_cpio, 0, NULL, "", "", NULL },
+    
     { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd, 0, NULL, "", "", NULL },
     { "vt_dump_menu", ventoy_cmd_dump_menu, 0, NULL, "", "", NULL },
     { "vt_dynamic_menu", ventoy_cmd_dynamic_menu, 0, NULL, "", "", NULL },
@@ -2517,7 +2757,9 @@ static cmd_para ventoy_cmds[] =
     { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet, 0, NULL, "", "", NULL },
     { "vt_is_udf", ventoy_cmd_is_udf, 0, NULL, "", "", NULL },
     { "vt_file_size", ventoy_cmd_file_size, 0, NULL, "", "", NULL },
-    { "vt_load_iso_to_mem", ventoy_cmd_load_iso_to_mem, 0, NULL, "", "", NULL },
+    { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem, 0, NULL, "", "", NULL },
+    { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk, 0, NULL, "", "", NULL },
+    { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso, 0, NULL, "", "", NULL },
     
     { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect, 0, NULL, "{cfgfile}", "", NULL },
     { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect, 0, NULL, "{cfgfile}", "", NULL },
@@ -2557,6 +2799,9 @@ static cmd_para ventoy_cmds[] =
     { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko, 0, NULL, "", "", NULL },
     { "vt_unix_chain_data", ventoy_cmd_unix_chain_data, 0, NULL, "", "", NULL },
 
+    { "vt_img_hook_root", ventoy_cmd_img_hook_root, 0, NULL, "", "", NULL },
+    { "vt_img_unhook_root", ventoy_cmd_img_unhook_root, 0, NULL, "", "", NULL },
+
 };
 
 
index 75c222155cb2c46b2301b021256390cb7bfed838..a514f6b5605bf5035ddd518773d7b02293550c57 100644 (file)
@@ -467,6 +467,7 @@ grub_err_t ventoy_cmd_linux_locate_initrd(grub_extcmd_context_t ctxt, int argc,
 grub_err_t ventoy_cmd_initrd_count(grub_extcmd_context_t ctxt, int argc, char **args);
 grub_err_t ventoy_cmd_valid_initrd_count(grub_extcmd_context_t ctxt, int argc, char **args);
 grub_err_t ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **args);
+grub_err_t ventoy_cmd_trailer_cpio(grub_extcmd_context_t ctxt, int argc, char **args);
 int ventoy_cpio_newc_fill_head(void *buf, int filesize, const void *filedata, const char *name);
 grub_file_t ventoy_grub_file_open(enum grub_file_type type, const char *fmt, ...);
 grub_uint64_t ventoy_grub_get_file_size(const char *fmt, ...);
index ad871a10e5b7a15c1bbde8ec7184675a9737e3bd..dfda6a8433499726906aa92fff46cc769724eb5f 100644 (file)
@@ -564,6 +564,14 @@ grub_err_t ventoy_cmd_specify_initrd_file(grub_extcmd_context_t ctxt, int argc,
     VENTOY_CMD_RETURN(GRUB_ERR_NONE);
 }
 
+static int ventoy_cpio_newc_get_int(char *value)
+{
+    char buf[16] = {0};
+
+    grub_memcpy(buf, value, 8);
+    return (int)grub_strtoul(buf, NULL, 16);
+}
+
 static void ventoy_cpio_newc_fill_int(grub_uint32_t value, char *buf, int buflen)
 {
     int i;
@@ -1082,6 +1090,96 @@ grub_err_t ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **arg
     VENTOY_CMD_RETURN(GRUB_ERR_NONE);
 }
 
+grub_err_t ventoy_cmd_trailer_cpio(grub_extcmd_context_t ctxt, int argc, char **args)
+{
+    int mod;
+    int bufsize;
+    int namelen;
+    int offset;
+    char *name;
+    grub_uint8_t *bufend;
+    cpio_newc_header *head;
+    grub_file_t file;
+    char value[64];
+    const grub_uint8_t trailler[124] = {
+        0x30, 0x37, 0x30, 0x37, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+        0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+        0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30,
+        0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+        0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+        0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+        0x30, 0x30, 0x30, 0x30, 0x30, 0x42, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x54, 0x52,
+        0x41, 0x49, 0x4C, 0x45, 0x52, 0x21, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00 
+    };
+
+    (void)ctxt;
+    (void)argc;
+
+    file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", args[0], args[1]);
+    if (!file)
+    {
+        return 1;
+    }
+
+    grub_memset(g_ventoy_runtime_buf, 0, sizeof(ventoy_os_param));
+    ventoy_fill_os_param(file, (ventoy_os_param *)g_ventoy_runtime_buf);
+
+    grub_file_close(file);
+
+    grub_memcpy(g_ventoy_initrd_head, trailler, sizeof(trailler));
+    bufend = (grub_uint8_t *)g_ventoy_initrd_head + sizeof(trailler);
+
+    bufsize = (int)(bufend - g_ventoy_cpio_buf);
+    mod = bufsize % 512;
+    if (mod)
+    {
+        grub_memset(bufend, 0, 512 - mod);
+        bufsize += 512 - mod;
+    }
+
+    if (argc > 1 && grub_strcmp(args[2], "noinit") == 0)
+    {
+        head = (cpio_newc_header *)g_ventoy_cpio_buf;
+        name = (char *)(head + 1);
+
+        while (grub_strcmp(name, "TRAILER!!!"))
+        {
+            if (grub_strcmp(name, "init") == 0)
+            {
+                grub_memcpy(name, "xxxx", 4);
+            }
+            else if (grub_strcmp(name, "linuxrc") == 0)
+            {
+                grub_memcpy(name, "vtoyxrc", 7);
+            }
+            else if (grub_strcmp(name, "sbin") == 0)
+            {
+                grub_memcpy(name, "vtoy", 4);
+            }
+            else if (grub_strcmp(name, "sbin/init") == 0)
+            {
+                grub_memcpy(name, "vtoy/vtoy", 9);
+            }
+
+            namelen = ventoy_cpio_newc_get_int(head->c_namesize);
+            offset = sizeof(cpio_newc_header) + namelen;
+            offset = ventoy_align(offset, 4);
+            offset += ventoy_cpio_newc_get_int(head->c_filesize);
+            offset = ventoy_align(offset, 4);
+            
+            head = (cpio_newc_header *)((char *)head + offset);
+            name = (char *)(head + 1);
+        }
+    }
+    
+    grub_snprintf(value, sizeof(value), "0x%llx", (ulonglong)(ulong)g_ventoy_cpio_buf);
+    ventoy_set_env("ventoy_cpio_addr", value);
+    grub_snprintf(value, sizeof(value), "%d", bufsize);
+    ventoy_set_env("ventoy_cpio_size", value);
+
+    VENTOY_CMD_RETURN(GRUB_ERR_NONE);
+}
+
 
 grub_err_t ventoy_cmd_linux_chain_data(grub_extcmd_context_t ctxt, int argc, char **args)
 {
index 7fbe9db749b34cf8e506ce630fd84309fcaa08c3..426e75fc051f81ebafdc1213ff0e2b54a87ad0fe 100644 (file)
@@ -151,6 +151,12 @@ static int ventoy_plugin_theme_check(VTOY_JSON *json, const char *isodisk)
         grub_printf("display_mode: %s\n", value);
     }
 
+    value = vtoy_json_get_string_ex(json->pstChild, "serial_param");
+    if (value)
+    {
+        grub_printf("serial_param %s\n", value);
+    }
+
     value = vtoy_json_get_string_ex(json->pstChild, "ventoy_left");
     if (value)
     {
@@ -236,6 +242,13 @@ static int ventoy_plugin_theme_entry(VTOY_JSON *json, const char *isodisk)
         debug("display_mode %s\n", value);
         grub_env_set("vtoy_display_mode", value);
     }
+    
+    value = vtoy_json_get_string_ex(json->pstChild, "serial_param");
+    if (value)
+    {
+        debug("serial_param %s\n", value);
+        grub_env_set("vtoy_serial_param", value);
+    }
 
     value = vtoy_json_get_string_ex(json->pstChild, "ventoy_left");
     if (value)
diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_unix.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_unix.c
new file mode 100644 (file)
index 0000000..1e81309
--- /dev/null
@@ -0,0 +1,631 @@
+/******************************************************************************
+ * ventoy_unix.c 
+ *
+ * Copyright (c) 2020, longpanda <admin@ventoy.net>
+ *
+ * This program 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.
+ * 
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/disk.h>
+#include <grub/device.h>
+#include <grub/term.h>
+#include <grub/partition.h>
+#include <grub/file.h>
+#include <grub/normal.h>
+#include <grub/extcmd.h>
+#include <grub/datetime.h>
+#include <grub/i18n.h>
+#include <grub/net.h>
+#include <grub/time.h>
+#include <grub/ventoy.h>
+#include "ventoy_def.h"
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+char g_ko_mod_path[256];
+int g_conf_new_len = 0;
+char *g_conf_new_data = NULL;
+
+int g_mod_new_len = 0;
+char *g_mod_new_data = NULL;
+
+grub_uint64_t g_mod_override_offset = 0;
+grub_uint64_t g_conf_override_offset = 0;
+
+static int ventoy_get_file_override(const char *filename, grub_uint64_t *offset)
+{
+    grub_file_t file;
+
+    *offset = 0;
+
+    file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "(loop)%s", filename);
+    if (!file)
+    {
+        return 1;
+    }
+
+    *offset = grub_iso9660_get_last_file_dirent_pos(file) + 2;
+    
+    grub_file_close(file);
+    
+    return 0;
+}
+
+static grub_uint32_t ventoy_unix_get_override_chunk_count(void)
+{
+    grub_uint32_t count = 0;
+
+    if (g_conf_new_len > 0)
+    {
+        count++;
+    }
+    
+    if (g_mod_new_len > 0)
+    {
+        count++;
+    }
+
+    return count;
+}
+
+static grub_uint32_t ventoy_unix_get_virt_chunk_count(void)
+{
+    grub_uint32_t count = 0;
+
+    if (g_conf_new_len > 0)
+    {
+        count++;
+    }
+    
+    if (g_mod_new_len > 0)
+    {
+        count++;
+    }
+
+    return count;
+}
+static grub_uint32_t ventoy_unix_get_virt_chunk_size(void)
+{
+    grub_uint32_t size;
+
+    size = sizeof(ventoy_virt_chunk) * ventoy_unix_get_virt_chunk_count();
+
+    if (g_conf_new_len > 0)
+    {
+        size += ventoy_align_2k(g_conf_new_len);
+    }
+    
+    if (g_mod_new_len > 0)
+    {
+        size += ventoy_align_2k(g_mod_new_len);
+    }
+
+    return size;
+}
+
+static void ventoy_unix_fill_override_data(    grub_uint64_t isosize, void *override)
+{
+    grub_uint64_t sector;
+    ventoy_override_chunk *cur;
+    ventoy_iso9660_override *dirent;
+    
+    sector = (isosize + 2047) / 2048;
+
+    cur = (ventoy_override_chunk *)override;
+
+    if (g_conf_new_len > 0)
+    {
+        /* loader.conf */
+        cur->img_offset = g_conf_override_offset;
+        cur->override_size = sizeof(ventoy_iso9660_override);
+        dirent = (ventoy_iso9660_override *)cur->override_data;
+        dirent->first_sector    = (grub_uint32_t)sector;
+        dirent->size            = (grub_uint32_t)g_conf_new_len;
+        dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector);
+        dirent->size_be         = grub_swap_bytes32(dirent->size);
+        sector += (dirent->size + 2047) / 2048;
+    }
+
+    if (g_mod_new_len > 0)
+    {
+        /* mod.ko */
+        cur++;
+        cur->img_offset = g_mod_override_offset;
+        cur->override_size = sizeof(ventoy_iso9660_override);
+        dirent = (ventoy_iso9660_override *)cur->override_data;
+        dirent->first_sector    = (grub_uint32_t)sector;
+        dirent->size            = (grub_uint32_t)g_mod_new_len;
+        dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector);
+        dirent->size_be         = grub_swap_bytes32(dirent->size);
+        sector += (dirent->size + 2047) / 2048;
+    }
+
+    return;
+}
+
+static void ventoy_unix_fill_virt_data(    grub_uint64_t isosize, ventoy_chain_head *chain)
+{
+    grub_uint64_t sector;
+    grub_uint32_t offset;
+    grub_uint32_t data_secs;
+    char *override;
+    ventoy_virt_chunk *cur;
+
+    override = (char *)chain + chain->virt_chunk_offset;
+    cur = (ventoy_virt_chunk *)override;
+    
+    sector = (isosize + 2047) / 2048;
+    offset = 2 * sizeof(ventoy_virt_chunk);
+
+    if (g_conf_new_len > 0)
+    {
+        ventoy_unix_fill_virt(g_conf_new_data, g_conf_new_len);
+    }
+
+    if (g_mod_new_len > 0)
+    {
+        ventoy_unix_fill_virt(g_mod_new_data, g_mod_new_len);
+    }
+    
+    return;
+}
+
+static int ventoy_freebsd_append_conf(char *buf, const char *isopath)
+{
+    int pos = 0;
+    grub_uint32_t i;
+    grub_disk_t disk;
+    grub_file_t isofile;
+    char uuid[64] = {0};
+    ventoy_img_chunk *chunk;
+    grub_uint8_t disk_guid[16];
+
+    debug("ventoy_freebsd_append_conf %s\n", isopath);
+    
+    isofile = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", isopath);
+    if (!isofile)
+    {
+        return 1;
+    }
+
+    vtoy_ssprintf(buf, pos, "ventoy_load=\"%s\"\n", "YES");
+    vtoy_ssprintf(buf, pos, "ventoy_name=\"%s\"\n", g_ko_mod_path);
+
+    disk = isofile->device->disk;
+
+    ventoy_get_disk_guid(isofile->name, disk_guid);
+
+    for (i = 0; i < 16; i++)
+    {
+        grub_snprintf(uuid + i * 2, sizeof(uuid), "%02x", disk_guid[i]);
+    }
+
+    vtoy_ssprintf(buf, pos, "hint.ventoy.0.disksize=%llu\n", (ulonglong)(disk->total_sectors * (1 << disk->log_sector_size)));
+    vtoy_ssprintf(buf, pos, "hint.ventoy.0.diskuuid=\"%s\"\n", uuid);    
+    vtoy_ssprintf(buf, pos, "hint.ventoy.0.segnum=%u\n", g_img_chunk_list.cur_chunk);
+
+    for (i = 0; i < g_img_chunk_list.cur_chunk; i++)
+    {
+        chunk = g_img_chunk_list.chunk + i;
+        vtoy_ssprintf(buf, pos, "hint.ventoy.%u.seg=\"0x%llx@0x%llx\"\n", 
+            i, (ulonglong)(chunk->disk_start_sector * 512),
+            (ulonglong)((chunk->disk_end_sector + 1) * 512));
+    }
+
+    grub_file_close(isofile);
+
+    return pos;
+}
+
+grub_err_t ventoy_cmd_unix_reset(grub_extcmd_context_t ctxt, int argc, char **args)
+{
+    (void)ctxt;
+    (void)argc;
+    (void)args;
+    
+    g_conf_new_len = 0;
+    g_mod_new_len = 0;
+    g_mod_override_offset = 0;
+    g_conf_override_offset = 0;
+
+    check_free(g_mod_new_data, grub_free);
+    check_free(g_conf_new_data, grub_free);
+
+    VENTOY_CMD_RETURN(GRUB_ERR_NONE);
+}
+
+grub_err_t ventoy_cmd_parse_freenas_ver(grub_extcmd_context_t ctxt, int argc, char **args)
+{
+    grub_file_t file;
+    const char *ver = NULL;
+    char *buf = NULL;
+    VTOY_JSON *json = NULL;
+    
+    (void)ctxt;
+    (void)argc;
+
+    file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
+    if (!file)
+    {
+        debug("Failed to open file %s\n", args[0]);
+        return 1;
+    }
+
+    buf = grub_malloc(file->size + 2);
+    if (!buf)
+    {
+        grub_file_close(file);
+        return 0;
+    }
+    grub_file_read(file, buf, file->size);
+    buf[file->size] = 0;
+
+    json = vtoy_json_create();
+    if (!json)
+    {
+        goto end;
+    }
+
+    if (vtoy_json_parse(json, buf))
+    {
+        goto end;
+    }
+
+    ver = vtoy_json_get_string_ex(json->pstChild, "Version");
+    if (ver)
+    {
+        debug("freenas version:<%s>\n", ver);
+        ventoy_set_env(args[1], ver);
+    }
+    else
+    {
+        debug("freenas version:<%s>\n", "NOT FOUND");
+        grub_env_unset(args[1]);
+    }
+
+end:
+    grub_check_free(buf);
+    check_free(json, vtoy_json_destroy);
+    grub_file_close(file);
+
+    VENTOY_CMD_RETURN(GRUB_ERR_NONE);
+}
+
+grub_err_t ventoy_cmd_unix_freebsd_ver(grub_extcmd_context_t ctxt, int argc, char **args)
+{
+    grub_file_t file;
+    char *buf;
+    char *start = NULL;
+    char *nextline = NULL;
+    
+    (void)ctxt;
+    (void)argc;
+    (void)args;
+
+    file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s", args[0]);
+    if (!file)
+    {
+        debug("Failed to open file %s\n", args[0]);
+        return 1;
+    }
+
+    buf = grub_zalloc(file->size + 2);
+    if (!buf)
+    {
+        grub_file_close(file);
+        return 0;
+    }
+    grub_file_read(file, buf, file->size);
+
+    for (start = buf; start; start = nextline)
+    {
+        if (grub_strncmp(start, "USERLAND_VERSION", 16) == 0)
+        {
+            nextline = start;
+            while (*nextline && *nextline != '\r' && *nextline != '\n')
+            {
+                nextline++;
+            }
+
+            *nextline = 0;            
+            break;
+        }
+        nextline = ventoy_get_line(start);
+    }
+
+    if (start)
+    {
+        debug("freebsd version:<%s>\n", start);
+        ventoy_set_env(args[1], start);
+    }
+    else
+    {
+        debug("freebsd version:<%s>\n", "NOT FOUND");
+        grub_env_unset(args[1]);
+    }
+
+    grub_free(buf);
+    grub_file_close(file);
+    
+    VENTOY_CMD_RETURN(GRUB_ERR_NONE);
+}
+
+grub_err_t ventoy_cmd_unix_replace_conf(grub_extcmd_context_t ctxt, int argc, char **args)
+{
+    grub_uint32_t i;
+    char *data;
+    grub_uint64_t offset;
+    grub_file_t file;
+    const char *confile = NULL;
+    const char * loader_conf[] = 
+    {
+        "/boot/loader.conf",
+        "/boot/defaults/loader.conf",
+    };
+
+    (void)ctxt;
+
+    if (argc != 2)
+    {
+        debug("Replace conf invalid argc %d\n", argc);
+        return 1;
+    }
+    for (i = 0; i < sizeof(loader_conf) / sizeof(loader_conf[0]); i++)
+    {
+        if (ventoy_get_file_override(loader_conf[i], &offset) == 0)
+        {
+            confile = loader_conf[i];
+            g_conf_override_offset = offset;
+            break;
+        }
+    }
+
+    if (confile == NULL)
+    {   
+        debug("Can't find loader.conf file from %u locations\n", i);
+        return 1;
+    }
+
+    file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "(loop)/%s", confile);
+    if (!file)
+    {
+        debug("Failed to open %s \n", confile);
+        return 1;
+    }
+
+    debug("old conf file size:%d\n", (int)file->size);
+
+    data = grub_malloc(VTOY_MAX_SCRIPT_BUF);
+    if (!data)
+    {
+        grub_file_close(file);    
+        return 1;
+    }
+
+    grub_file_read(file, data, file->size);
+    grub_file_close(file);
+    
+    g_conf_new_data = data;
+    g_conf_new_len = (int)file->size;
+
+    if (grub_strcmp(args[0], "FreeBSD") == 0)
+    {
+        g_conf_new_len += ventoy_freebsd_append_conf(data + file->size, args[1]);
+    }
+    
+    VENTOY_CMD_RETURN(GRUB_ERR_NONE);
+}
+
+grub_err_t ventoy_cmd_unix_replace_ko(grub_extcmd_context_t ctxt, int argc, char **args)
+{
+    char *data;
+    grub_uint64_t offset;
+    grub_file_t file;
+
+    (void)ctxt;
+
+    if (argc != 2)
+    {
+        debug("Replace ko invalid argc %d\n", argc);
+        return 1;
+    }
+
+    debug("replace ko %s\n", args[0]);
+
+    if (ventoy_get_file_override(args[0], &offset) == 0)
+    {
+        grub_snprintf(g_ko_mod_path, sizeof(g_ko_mod_path), "%s", args[0]);
+        g_mod_override_offset = offset;
+    }
+    else
+    {   
+        debug("Can't find replace ko file from %s\n", args[0]);
+        return 1;
+    }
+
+    file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s", args[1]);
+    if (!file)
+    {
+        debug("Failed to open %s \n", args[1]);
+        return 1;
+    }
+
+    debug("new ko file size:%d\n", (int)file->size);
+
+    data = grub_malloc(file->size);
+    if (!data)
+    {
+        grub_file_close(file);    
+        return 1;
+    }
+
+    grub_file_read(file, data, file->size);
+    grub_file_close(file);
+    
+    g_mod_new_data = data;
+    g_mod_new_len = (int)file->size;
+    
+    VENTOY_CMD_RETURN(GRUB_ERR_NONE);
+}
+
+grub_err_t ventoy_cmd_unix_chain_data(grub_extcmd_context_t ctxt, int argc, char **args)
+{
+    int ventoy_compatible = 0;
+    grub_uint32_t size = 0;
+    grub_uint64_t isosize = 0;
+    grub_uint32_t boot_catlog = 0;
+    grub_uint32_t img_chunk_size = 0;
+    grub_uint32_t override_count = 0;
+    grub_uint32_t override_size = 0;
+    grub_uint32_t virt_chunk_size = 0;
+    grub_file_t file;
+    grub_disk_t disk;
+    const char *pLastChain = NULL;
+    const char *compatible;
+    ventoy_chain_head *chain;
+    char envbuf[64];
+    
+    (void)ctxt;
+    (void)argc;
+
+    compatible = grub_env_get("ventoy_compatible");
+    if (compatible && compatible[0] == 'Y')
+    {
+        ventoy_compatible = 1;
+    }
+
+    if (NULL == g_img_chunk_list.chunk)
+    {
+        grub_printf("ventoy not ready\n");
+        return 1;
+    }
+
+    file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
+    if (!file)
+    {
+        return 1;
+    }
+
+    isosize = file->size;
+
+    boot_catlog = ventoy_get_iso_boot_catlog(file);
+    if (boot_catlog)
+    {
+        if (ventoy_is_efi_os() && (!ventoy_has_efi_eltorito(file, boot_catlog)))
+        {
+            grub_env_set("LoadIsoEfiDriver", "on");
+        }
+    }
+    else
+    {
+        if (ventoy_is_efi_os())
+        {
+            grub_env_set("LoadIsoEfiDriver", "on");
+        }
+        else
+        {
+            return grub_error(GRUB_ERR_BAD_ARGUMENT, "File %s is not bootable", args[0]);
+        }
+    }
+    
+    img_chunk_size = g_img_chunk_list.cur_chunk * sizeof(ventoy_img_chunk);
+    
+    if (ventoy_compatible)
+    {
+        size = sizeof(ventoy_chain_head) + img_chunk_size;
+    }
+    else
+    {
+        override_count = ventoy_unix_get_override_chunk_count();
+        override_size = override_count * sizeof(ventoy_override_chunk);
+        
+        virt_chunk_size = ventoy_unix_get_virt_chunk_size();
+        size = sizeof(ventoy_chain_head) + img_chunk_size + override_size + virt_chunk_size;
+    }
+    
+    pLastChain = grub_env_get("vtoy_chain_mem_addr");
+    if (pLastChain)
+    {
+        chain = (ventoy_chain_head *)grub_strtoul(pLastChain, NULL, 16);
+        if (chain)
+        {
+            debug("free last chain memory %p\n", chain);
+            grub_free(chain);
+        }
+    }
+
+    chain = grub_malloc(size);
+    if (!chain)
+    {
+        grub_printf("Failed to alloc chain memory size %u\n", size);
+        grub_file_close(file);
+        return 1;
+    }
+
+    grub_snprintf(envbuf, sizeof(envbuf), "0x%lx", (unsigned long)chain);
+    grub_env_set("vtoy_chain_mem_addr", envbuf);
+    grub_snprintf(envbuf, sizeof(envbuf), "%u", size);
+    grub_env_set("vtoy_chain_mem_size", envbuf);
+
+    grub_memset(chain, 0, sizeof(ventoy_chain_head));
+
+    /* part 1: os parameter */
+    g_ventoy_chain_type = ventoy_chain_linux;
+    ventoy_fill_os_param(file, &(chain->os_param));
+
+    /* part 2: chain head */
+    disk = file->device->disk;
+    chain->disk_drive = disk->id;
+    chain->disk_sector_size = (1 << disk->log_sector_size);
+    chain->real_img_size_in_bytes = file->size;
+    chain->virt_img_size_in_bytes = (file->size + 2047) / 2048 * 2048;
+    chain->boot_catalog = boot_catlog;
+
+    if (!ventoy_is_efi_os())
+    {
+        grub_file_seek(file, boot_catlog * 2048);
+        grub_file_read(file, chain->boot_catalog_sector, sizeof(chain->boot_catalog_sector));
+    }
+
+    /* part 3: image chunk */
+    chain->img_chunk_offset = sizeof(ventoy_chain_head);
+    chain->img_chunk_num = g_img_chunk_list.cur_chunk;
+    grub_memcpy((char *)chain + chain->img_chunk_offset, g_img_chunk_list.chunk, img_chunk_size);
+
+    if (ventoy_compatible)
+    {
+        return 0;
+    }
+
+    /* part 4: override chunk */
+    chain->override_chunk_offset = chain->img_chunk_offset + img_chunk_size;
+    chain->override_chunk_num = override_count;
+    ventoy_unix_fill_override_data(isosize, (char *)chain + chain->override_chunk_offset);
+
+    /* part 5: virt chunk */
+    chain->virt_chunk_offset = chain->override_chunk_offset + override_size;
+    chain->virt_chunk_num = ventoy_unix_get_virt_chunk_count();
+    ventoy_unix_fill_virt_data(isosize, chain);
+
+    grub_file_close(file);
+    
+    VENTOY_CMD_RETURN(GRUB_ERR_NONE);
+}
+
diff --git a/GRUB2/MOD_SRC/grub-2.04/include/grub/compiler.h b/GRUB2/MOD_SRC/grub-2.04/include/grub/compiler.h
new file mode 100644 (file)
index 0000000..9859ff4
--- /dev/null
@@ -0,0 +1,53 @@
+/* compiler.h - macros for various compiler features */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2005,2006,2007,2008,2009,2010,2014  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/>.
+ */
+
+#ifndef GRUB_COMPILER_HEADER
+#define GRUB_COMPILER_HEADER   1
+
+/* GCC version checking borrowed from glibc. */
+#if defined(__GNUC__) && defined(__GNUC_MINOR__)
+#  define GNUC_PREREQ(maj,min) \
+       ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+#else
+#  define GNUC_PREREQ(maj,min) 0
+#endif
+
+/* Does this compiler support compile-time error attributes? */
+#if GNUC_PREREQ(4,3)
+#  define ATTRIBUTE_ERROR(msg) \
+       __attribute__ ((__error__ (msg)))
+#else
+#  define ATTRIBUTE_ERROR(msg) __attribute__ ((noreturn))
+#endif
+
+#if GNUC_PREREQ(4,4)
+#  define GNU_PRINTF gnu_printf
+#else
+#  define GNU_PRINTF printf
+#endif
+
+#if GNUC_PREREQ(3,4)
+#  define WARN_UNUSED_RESULT __attribute__ ((warn_unused_result))
+#else
+#  define WARN_UNUSED_RESULT
+#endif
+
+#define UNUSED __attribute__((__unused__))
+
+#endif /* ! GRUB_COMPILER_HEADER */
diff --git a/GRUB2/MOD_SRC/grub-2.04/include/grub/kernel.h b/GRUB2/MOD_SRC/grub-2.04/include/grub/kernel.h
new file mode 100644 (file)
index 0000000..55c1c12
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2005,2006,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/>.
+ */
+
+#ifndef GRUB_KERNEL_HEADER
+#define GRUB_KERNEL_HEADER     1
+
+#include <grub/types.h>
+#include <grub/symbol.h>
+
+enum
+{
+  OBJ_TYPE_ELF,
+  OBJ_TYPE_MEMDISK,
+  OBJ_TYPE_CONFIG,
+  OBJ_TYPE_PREFIX,
+  OBJ_TYPE_PUBKEY,
+  OBJ_TYPE_DTB
+};
+
+/* The module header.  */
+struct grub_module_header
+{
+  /* The type of object.  */
+  grub_uint32_t type;
+  /* The size of object (including this header).  */
+  grub_uint32_t size;
+};
+
+/* "gmim" (GRUB Module Info Magic).  */
+#define GRUB_MODULE_MAGIC 0x676d696d
+
+struct grub_module_info32
+{
+  /* Magic number so we know we have modules present.  */
+  grub_uint32_t magic;
+  /* The offset of the modules.  */
+  grub_uint32_t offset;
+  /* The size of all modules plus this header.  */
+  grub_uint32_t size;
+};
+
+struct grub_module_info64
+{
+  /* Magic number so we know we have modules present.  */
+  grub_uint32_t magic;
+  grub_uint32_t padding;
+  /* The offset of the modules.  */
+  grub_uint64_t offset;
+  /* The size of all modules plus this header.  */
+  grub_uint64_t size;
+};
+
+#ifndef GRUB_UTIL
+/* Space isn't reusable on some platforms.  */
+/* On Qemu the preload space is readonly.  */
+/* On emu there is no preload space.  */
+/* On ieee1275 our code assumes that heap is p=v which isn't guaranteed for module space.  */
+#if defined (GRUB_MACHINE_QEMU) || defined (GRUB_MACHINE_EMU) \
+  || defined (GRUB_MACHINE_EFI) \
+  || (defined (GRUB_MACHINE_IEEE1275) && !defined (__sparc__))
+#define GRUB_KERNEL_PRELOAD_SPACE_REUSABLE 0
+#endif
+
+#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) \
+  || defined (GRUB_MACHINE_MULTIBOOT) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS) \
+  || defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_ARC) \
+  || (defined (__sparc__) && defined (GRUB_MACHINE_IEEE1275)) \
+  || defined (GRUB_MACHINE_UBOOT) || defined (GRUB_MACHINE_XEN) \
+  || defined(GRUB_MACHINE_XEN_PVH)
+/* FIXME: stack is between 2 heap regions. Move it.  */
+#define GRUB_KERNEL_PRELOAD_SPACE_REUSABLE 1
+#endif
+
+#ifndef GRUB_KERNEL_PRELOAD_SPACE_REUSABLE
+#error "Please check if preload space is reusable on this platform!"
+#endif
+
+#if GRUB_TARGET_SIZEOF_VOID_P == 8
+#define grub_module_info grub_module_info64
+#else
+#define grub_module_info grub_module_info32
+#endif
+
+extern grub_addr_t EXPORT_VAR (grub_modbase);
+
+void EXPORT_FUNC(ventoy_env_hook_root)(int hook);
+
+#define FOR_MODULES(var)  for (\
+  var = (grub_modbase && ((((struct grub_module_info *) grub_modbase)->magic) == GRUB_MODULE_MAGIC)) ? (struct grub_module_header *) \
+    (grub_modbase + (((struct grub_module_info *) grub_modbase)->offset)) : 0;\
+  var && (grub_addr_t) var \
+    < (grub_modbase + (((struct grub_module_info *) grub_modbase)->size));    \
+  var = (struct grub_module_header *)                                  \
+    (((grub_uint32_t *) var) + ((((struct grub_module_header *) var)->size + sizeof (grub_addr_t) - 1) / sizeof (grub_addr_t)) * (sizeof (grub_addr_t) / sizeof (grub_uint32_t))))
+
+grub_addr_t grub_modules_get_end (void);
+
+#endif
+
+/* The start point of the C code.  */
+void grub_main (void) __attribute__ ((noreturn));
+
+/* The machine-specific initialization. This must initialize memory.  */
+void grub_machine_init (void);
+
+/* The machine-specific finalization.  */
+void EXPORT_FUNC(grub_machine_fini) (int flags);
+
+/* The machine-specific prefix initialization.  */
+void
+grub_machine_get_bootlocation (char **device, char **path);
+
+/* Register all the exported symbols. This is automatically generated.  */
+void grub_register_exported_symbols (void);
+
+extern void (*EXPORT_VAR(grub_net_poll_cards_idle)) (void);
+
+#endif /* ! GRUB_KERNEL_HEADER */
diff --git a/GRUB2/MOD_SRC/grub-2.04/include/grub/menu.h b/GRUB2/MOD_SRC/grub-2.04/include/grub/menu.h
new file mode 100644 (file)
index 0000000..0acdc2a
--- /dev/null
@@ -0,0 +1,119 @@
+/* menu.h - Menu model function prototypes and data structures. */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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/>.
+ */
+
+#ifndef GRUB_MENU_HEADER
+#define GRUB_MENU_HEADER 1
+
+struct bls_entry
+{
+  struct bls_entry *next;
+  struct bls_entry *prev;
+  struct keyval **keyvals;
+  int nkeyvals;
+  char *filename;
+  int visible;
+};
+
+struct grub_menu_entry_class
+{
+  char *name;
+  struct grub_menu_entry_class *next;
+};
+
+/* The menu entry.  */
+struct grub_menu_entry
+{
+  /* The title name.  */
+  const char *title;
+
+  /* The identifier.  */
+  const char *id;
+
+  /* If set means not everybody is allowed to boot this entry.  */
+  int restricted;
+
+  /* Allowed users.  */
+  const char *users;
+
+  /* The classes associated with the menu entry:
+     used to choose an icon or other style attributes.
+     This is a dummy head node for the linked list, so for an entry E,
+     E.classes->next is the first class if it is not NULL.  */
+  struct grub_menu_entry_class *classes;
+
+  /* The sourcecode of the menu entry, used by the editor.  */
+  const char *sourcecode;
+
+  /* Parameters to be passed to menu definition.  */
+  int argc;
+  char **args;
+
+  int hotkey;
+
+  int submenu;
+
+  /* The next element.  */
+  struct grub_menu_entry *next;
+
+  /* BLS used to populate the entry */
+  struct bls_entry *bls;
+};
+typedef struct grub_menu_entry *grub_menu_entry_t;
+
+/* The menu.  */
+struct grub_menu
+{
+  /* The size of a menu.  */
+  int size;
+
+  /* The list of menu entries.  */
+  grub_menu_entry_t entry_list;
+};
+typedef struct grub_menu *grub_menu_t;
+
+/* Callback structure menu viewers can use to provide user feedback when
+   default entries are executed, possibly including fallback entries.  */
+typedef struct grub_menu_execute_callback
+{
+  /* Called immediately before ENTRY is booted.  */
+  void (*notify_booting) (grub_menu_entry_t entry, void *userdata);
+
+  /* Called when executing one entry has failed, and another entry, ENTRY, will
+     be executed as a fallback.  The implementation of this function should
+     delay for a period of at least 2 seconds before returning in order to
+     allow the user time to read the information before it can be lost by
+     executing ENTRY.  */
+  void (*notify_fallback) (grub_menu_entry_t entry, void *userdata);
+
+  /* Called when an entry has failed to execute and there is no remaining
+     fallback entry to attempt.  */
+  void (*notify_failure) (void *userdata);
+}
+*grub_menu_execute_callback_t;
+
+grub_menu_entry_t grub_menu_get_entry (grub_menu_t menu, int no);
+int grub_menu_get_timeout (void);
+void grub_menu_set_timeout (int timeout);
+void grub_menu_entry_run (grub_menu_entry_t entry);
+int grub_menu_get_default_entry_index (grub_menu_t menu);
+
+void grub_menu_init (void);
+void grub_menu_fini (void);
+
+#endif /* GRUB_MENU_HEADER */
diff --git a/GRUB2/MOD_SRC/grub-2.04/include/grub/normal.h b/GRUB2/MOD_SRC/grub-2.04/include/grub/normal.h
new file mode 100644 (file)
index 0000000..8839ad8
--- /dev/null
@@ -0,0 +1,177 @@
+/* normal.h - prototypes for the normal mode */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2005,2006,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/>.
+ */
+
+#ifndef GRUB_NORMAL_HEADER
+#define GRUB_NORMAL_HEADER     1
+
+#include <grub/term.h>
+#include <grub/symbol.h>
+#include <grub/err.h>
+#include <grub/env.h>
+#include <grub/menu.h>
+#include <grub/command.h>
+#include <grub/file.h>
+
+/* The standard left and right margin for some messages.  */
+#define STANDARD_MARGIN 6
+
+/* The type of a completion item.  */
+enum grub_completion_type
+  {
+    GRUB_COMPLETION_TYPE_COMMAND,
+    GRUB_COMPLETION_TYPE_DEVICE,
+    GRUB_COMPLETION_TYPE_PARTITION,
+    GRUB_COMPLETION_TYPE_FILE,
+    GRUB_COMPLETION_TYPE_ARGUMENT
+  };
+typedef enum grub_completion_type grub_completion_type_t;
+
+extern struct grub_menu_viewer grub_normal_text_menu_viewer;
+extern int grub_normal_exit_level;
+
+/* Defined in `main.c'.  */
+void grub_enter_normal_mode (const char *config);
+void grub_normal_execute (const char *config, int nested, int batch);
+struct grub_term_screen_geometry
+{
+  /* The number of entries shown at a time.  */
+  int num_entries;
+  int first_entry_y;
+  int first_entry_x;
+  int entry_width;
+  int timeout_y;
+  int timeout_lines;
+  int border;
+  int right_margin;
+};
+
+void grub_menu_init_page (int nested, int edit,
+                         struct grub_term_screen_geometry *geo,
+                         struct grub_term_output *term);
+void grub_normal_init_page (struct grub_term_output *term, int y);
+char *grub_file_getline (grub_file_t file);
+void grub_cmdline_run (int nested, int force_auth);
+
+/* Defined in `cmdline.c'.  */
+char *grub_cmdline_get (const char *prompt);
+grub_err_t grub_set_history (int newsize);
+
+/* Defined in `completion.c'.  */
+char *grub_normal_do_completion (char *buf, int *restore,
+                                void (*hook) (const char *item, grub_completion_type_t type, int count));
+
+/* Defined in `misc.c'.  */
+grub_err_t grub_normal_print_device_info (const char *name);
+
+/* Defined in `color.c'.  */
+char *grub_env_write_color_normal (struct grub_env_var *var, const char *val);
+char *grub_env_write_color_highlight (struct grub_env_var *var, const char *val);
+int grub_parse_color_name_pair (grub_uint8_t *ret, const char *name);
+
+/* Defined in `menu_text.c'.  */
+void grub_wait_after_message (void);
+void
+grub_print_ucs4 (const grub_uint32_t * str,
+                const grub_uint32_t * last_position,
+                int margin_left, int margin_right,
+                struct grub_term_output *term);
+
+void
+grub_print_ucs4_menu (const grub_uint32_t * str,
+                     const grub_uint32_t * last_position,
+                     int margin_left, int margin_right,
+                     struct grub_term_output *term,
+                     int skip_lines, int max_lines, grub_uint32_t contchar,
+                     struct grub_term_pos *pos);
+int
+grub_ucs4_count_lines (const grub_uint32_t * str,
+                      const grub_uint32_t * last_position,
+                      int margin_left, int margin_right,
+                      struct grub_term_output *term);
+grub_size_t grub_getstringwidth (grub_uint32_t * str,
+                                const grub_uint32_t * last_position,
+                                struct grub_term_output *term);
+void grub_print_message_indented (const char *msg, int margin_left,
+                                 int margin_right,
+                                 struct grub_term_output *term);
+void
+grub_menu_text_register_instances (int entry, grub_menu_t menu, int nested);
+grub_err_t
+grub_show_menu (grub_menu_t menu, int nested, int autobooted);
+
+/* Defined in `handler.c'.  */
+void read_handler_list (void);
+void free_handler_list (void);
+
+/* Defined in `dyncmd.c'.  */
+void read_command_list (const char *prefix);
+
+/* Defined in `autofs.c'.  */
+void read_fs_list (const char *prefix);
+
+void grub_context_init (void);
+void grub_context_fini (void);
+
+void read_crypto_list (const char *prefix);
+
+void read_terminal_list (const char *prefix);
+
+void grub_set_more (int onoff);
+
+void grub_normal_reset_more (void);
+
+void grub_xputs_normal (const char *str);
+
+extern int grub_extractor_level;
+
+grub_err_t
+grub_normal_add_menu_entry (int argc, const char **args, char **classes,
+                           const char *id,
+                           const char *users, const char *hotkey,
+                           const char *prefix, const char *sourcecode,
+                           int submenu, int *index, struct bls_entry *bls);
+
+grub_err_t
+grub_normal_set_password (const char *user, const char *password);
+
+void grub_normal_free_menu (grub_menu_t menu);
+
+void grub_normal_auth_init (void);
+void grub_normal_auth_fini (void);
+
+void
+grub_xnputs (const char *str, grub_size_t msg_len);
+
+grub_command_t
+grub_dyncmd_get_cmd (grub_command_t cmd);
+
+void
+grub_gettext_reread_prefix (const char *val);
+
+enum grub_human_size_type
+  {
+    GRUB_HUMAN_SIZE_NORMAL,
+    GRUB_HUMAN_SIZE_SHORT,
+    GRUB_HUMAN_SIZE_SPEED,
+  };
+
+const char *
+grub_get_human_size (grub_uint64_t size, enum grub_human_size_type type);
+
+#endif /* ! GRUB_NORMAL_HEADER */
index ef7b5d6d1a2df5a3830870362ae3abb0b2fcd60d..bd8e06dbd2b3830d66144a624d54661af92d5baa 100644 (file)
@@ -54,7 +54,8 @@ if [ -z "$VTOY_REDT_BUG" ]; then
 fi
 
 cd $VTOY_PATH
-xz -d ventoy.sh.xz
+xz -d ventoy_chain.sh.xz
+xz -d ventoy_loop.sh.xz
 
 if [ -n "$VTOY_REDT_BUG" ]; then
     xz -d -c hook.cpio.xz | cpio -idm
diff --git a/IMG/cpio/ventoy/hook/default/10-dm.rules b/IMG/cpio/ventoy/hook/default/10-dm.rules
new file mode 100644 (file)
index 0000000..f33df58
--- /dev/null
@@ -0,0 +1,150 @@
+# Copyright (C) 2009 Red Hat, Inc. All rights reserved.
+#
+# This file is part of LVM2.
+
+# Udev rules for device-mapper devices.
+#
+# These rules create a DM control node in /dev/mapper directory.
+# The rules also create nodes named dm-x (x is a number) in /dev
+# directory and symlinks to these nodes with names given by
+# the actual DM names. Some udev environment variables are set
+# for use in later rules:
+#   DM_NAME - actual DM device's name
+#   DM_UUID - UUID set for DM device (blank if not specified)
+#   DM_SUSPENDED - suspended state of DM device (0 or 1)
+#   DM_UDEV_RULES_VSN - DM udev rules version
+#
+# These rules cover only basic device-mapper functionality in udev.
+#
+# Various DM subsystems may contain further subsystem-specific rules
+# in 11-dm-<subsystem_name>.rules which should be installed together
+# with the DM subsystem and which extend these basic rules.
+# For example:
+#   11-dm-lvm.rules for LVM subsystem
+#   11-dm-mpath.rules for multipath subsystem (since version 0.6.0, recommended!)
+#
+# Even more specific rules may be required by subsystems so always
+# check subsystem's upstream repository for recent set of rules.
+# Also, keep in mind that recent rules may also require recent
+# subsystem-specific binaries.
+
+KERNEL=="device-mapper", NAME="mapper/control"
+
+SUBSYSTEM!="block", GOTO="dm_end"
+KERNEL!="dm-[0-9]*", GOTO="dm_end"
+
+
+# Device created, major and minor number assigned - "add" event generated.
+# Table loaded - no event generated.
+# Device resumed (or renamed) - "change" event generated.
+# Device removed - "remove" event generated.
+#
+# The dm-X nodes are always created, even on "add" event, we can't suppress
+# that (the node is created even earlier with devtmpfs). All the symlinks
+# (e.g. /dev/mapper) are created in right time after a device has its table
+# loaded and is properly resumed. For this reason, direct use of dm-X nodes
+# is not recommended.
+ACTION!="add|change", GOTO="dm_end"
+
+# Decode udev control flags and set environment variables appropriately.
+# These flags are encoded in DM_COOKIE variable that was introduced in
+# kernel version 2.6.31. Therefore, we can use this feature with
+# kernels >= 2.6.31 only. Cookie is not decoded for remove event.
+ENV{DM_COOKIE}=="?*", IMPORT{program}="/usr/sbin/dmsetup udevflags $env{DM_COOKIE}"
+
+# Rule out easy-to-detect inappropriate events first.
+ENV{DISK_RO}=="1", GOTO="dm_disable"
+
+# There is no cookie set nor any flags encoded in events not originating
+# in libdevmapper so we need to detect this and try to behave correctly.
+# For such spurious events, regenerate all flags from current udev database content
+# (this information would normally be inaccessible for spurious ADD and CHANGE events).
+ENV{DM_UDEV_PRIMARY_SOURCE_FLAG}=="1", ENV{DM_ACTIVATION}="1", GOTO="dm_flags_done"
+IMPORT{db}="DM_UDEV_DISABLE_DM_RULES_FLAG"
+IMPORT{db}="DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG"
+IMPORT{db}="DM_UDEV_DISABLE_DISK_RULES_FLAG"
+IMPORT{db}="DM_UDEV_DISABLE_OTHER_RULES_FLAG"
+IMPORT{db}="DM_UDEV_LOW_PRIORITY_FLAG"
+IMPORT{db}="DM_UDEV_DISABLE_LIBRARY_FALLBACK_FLAG"
+IMPORT{db}="DM_UDEV_PRIMARY_SOURCE_FLAG"
+IMPORT{db}="DM_UDEV_FLAG7"
+IMPORT{db}="DM_UDEV_RULES_VSN"
+LABEL="dm_flags_done"
+
+# Normally, we operate on "change" events. But when coldplugging, there's an
+# "add" event present. We have to recognize this and do our actions in this
+# particular situation, too. Also, we don't want the nodes to be created
+# prematurely on "add" events while not coldplugging. We check
+# DM_UDEV_PRIMARY_SOURCE_FLAG to see if the device was activated correctly
+# before and if not, we ignore the "add" event totally. This way we can support
+# udev triggers generating "add" events (e.g. "udevadm trigger --action=add" or
+# "echo add > /sys/block/<dm_device>/uevent"). The trigger with "add" event is
+# also used at boot to reevaluate udev rules for all existing devices activated
+# before (e.g. in initrd). If udev is used in initrd, we require the udev init
+# script to not remove the existing udev database so we can reuse the information
+# stored at the time of device activation in the initrd.
+ACTION!="add", GOTO="dm_no_coldplug"
+ENV{DM_UDEV_RULES_VSN}!="1", ENV{DM_UDEV_PRIMARY_SOURCE_FLAG}!="1", GOTO="dm_disable"
+ENV{DM_ACTIVATION}="1"
+LABEL="dm_no_coldplug"
+
+# Putting it together, following table is used to recognize genuine and spurious events.
+# N.B. Spurious events are generated based on use of the WATCH udev
+# rule or by triggering an event manually by "udevadm trigger" call
+# or by "echo <event_name> > /sys/block/dm-X/uevent".
+#
+#        EVENT              DM_UDEV_PRIMARY_SOURCE_FLAG   DM_ACTIVATION
+# ======================================================================
+# add event (genuine)                  0                        0
+# change event (genuine)               1                        1
+# add event (spurious)
+#   |_ dev still not active            0                        0
+#   \_ dev already active              1                        1
+# change event (spurious)
+#   |_ dev still not active            0                        0
+#   \_ dev already active              1                        0
+
+# "dm" sysfs subdirectory is available in newer versions of DM
+# only (kernels >= 2.6.29). We have to check for its existence
+# and use dmsetup tool instead to get the DM name, uuid and 
+# suspended state if the "dm" subdirectory is not present.
+# The "suspended" item was added even later (kernels >= 2.6.31),
+# so we also have to call dmsetup if the kernel version used
+# is in between these releases.
+TEST=="dm", ENV{DM_NAME}="$attr{dm/name}", ENV{DM_UUID}="$attr{dm/uuid}", ENV{DM_SUSPENDED}="$attr{dm/suspended}"
+TEST!="dm", IMPORT{program}="/usr/sbin/dmsetup info -j %M -m %m -c --nameprefixes --noheadings --rows -o name,uuid,suspended"
+ENV{DM_SUSPENDED}!="?*", IMPORT{program}="/usr/sbin/dmsetup info -j %M -m %m -c --nameprefixes --noheadings --rows -o suspended"
+
+# dmsetup tool provides suspended state information in textual
+# form with values "Suspended"/"Active". We translate it to
+# 0/1 respectively to be consistent with sysfs values.
+ENV{DM_SUSPENDED}=="Active", ENV{DM_SUSPENDED}="0"
+ENV{DM_SUSPENDED}=="Suspended", ENV{DM_SUSPENDED}="1"
+
+# This variable provides a reliable way to check that device-mapper
+# rules were installed. It means that all needed variables are set
+# by these rules directly so there's no need to acquire them again
+# later. Other rules can alternate the functionality based on this
+# fact (e.g. fallback to rules that behave correctly even without
+# these rules installed). It also provides versioning for any
+# possible future changes.
+# VSN 1 - original rules
+# VSN 2 - add support for synthesized events
+ENV{DM_UDEV_RULES_VSN}="2"
+
+ENV{DM_UDEV_DISABLE_DM_RULES_FLAG}!="1", ENV{DM_NAME}=="?*", SYMLINK+="mapper/$env{DM_NAME}"
+
+# Avoid processing and scanning a DM device in the other (foreign)
+# rules if it is in suspended state. However, we still keep 'disk'
+# and 'DM subsystem' related rules enabled in this case.
+ENV{DM_SUSPENDED}=="1", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1"
+
+GOTO="dm_end"
+
+LABEL="dm_disable"
+ENV{DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG}="1"
+ENV{DM_UDEV_DISABLE_DISK_RULES_FLAG}="1"
+ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1"
+OPTIONS:="nowatch"
+
+LABEL="dm_end"
index c656c6fe31c0c0e23538c35e3a6fe4e596482c34..2da5f07999b1ea960c5fbda61bfe28b3b0aefe5f 100644 (file)
@@ -475,7 +475,7 @@ ventoy_udev_disk_common_hook() {
 
 
 is_inotify_ventoy_part() {
-    if echo $1 | grep -q "2$"; then
+    if echo $1 | $GREP -q "2$"; then
         if ! [ -e /sys/block/$1 ]; then
             if [ -e /sys/class/block/$1 ]; then
                 if [ -e /dev/${1:0:-1} ]; then
index 05533347e45082ed14863ccd83532e5420b15e7e..fb36ac25f0d5405c10103f13caf4b52cfa950472 100644 (file)
@@ -105,3 +105,9 @@ ventoy_print_yum_repo() {
 ventoy_set_inotify_script() {
     echo $VTOY_PATH/hook/$1 > $VTOY_PATH/inotifyd-hook-script.txt
 }
+
+ventoy_set_loop_inotify_script() {
+    echo $VTOY_PATH/loop/$1 > $VTOY_PATH/inotifyd-loop-script.txt
+}
+
+
index ad5ac3a9ef149d8569a39017646f920a420ac22e..ef7310e6a481bd457266a764ddb4a443a855ef1e 100644 (file)
 #                                                                  #
 ####################################################################
 [ -d /proc ] || mkdir /proc; mount -t proc proc /proc
-vtcmdline=$(cat /proc/cmdline)
-vtkerver=$(cat /proc/version)
+vtoy_cmdline=$(cat /proc/cmdline)
 umount /proc; rm -rf /proc
 
-echo "kenel version=$vtkerver" >>$VTLOG
-echo "kenel cmdline=$vtcmdline" >>$VTLOG
-
-#break here for debug
-if [ "$VTOY_BREAK_LEVEL" = "01" ] || [ "$VTOY_BREAK_LEVEL" = "11" ]; then
-    sleep 5
-    echo -e "\n\n\033[32m ################################################# \033[0m"
-    echo -e "\033[32m ################ VENTOY DEBUG ################### \033[0m"
-    echo -e "\033[32m ################################################# \033[0m \n"
-    
-    if [ "$VTOY_BREAK_LEVEL" = "11" ]; then
-        cat $VTLOG
-    fi
-    exec $BUSYBOX_PATH/sh
-fi
-
-
-####################################################################
-#                                                                  #
-# Step 2 : extract real initramfs to /                             #
-#                                                                  #
-####################################################################
-cd /
-rm -rf /init /linuxrc /dev/  /root
-
-vtSbinFileNum=$(ls -1 /sbin | wc -l)
-if [ $vtSbinFileNum -eq 1 ]; then
-    echo "remove whole sbin directory" >> $VTLOG
-    rm -rf /sbin
+if echo $vtoy_cmdline | grep -q 'rdinit=/vtoy/vtoy'; then
+    echo "handover to init_loop" >>$VTLOG
+    rm -f /xxxx /vtoyxrc
+    exec $BUSYBOX_PATH/sh $VTOY_PATH/init_loop
 else
-    echo "remove only sbin/init file" >> $VTLOG
-    ls -l /sbin >> $VTLOG
-    rm -f /sbin/init
-fi
-
-ventoy_is_initrd_ramdisk() {
-    #As I known, PCLinuxOS use ramdisk
-    if echo $vtkerver | grep -i -q 'PCLinuxOS'; then
-        true
-    else
-        false
-    fi
-}
-
-ventoy_mount_squashfs() {
-    mkdir /dev
-    mount -t devtmpfs devtmpfs /dev    
-    dd if=$1 of=/dev/ram0 status=none
-    umount /dev && rm -rf /dev
-}
-
-# param: file skip magic tmp
-ventoy_unpack_initramfs() {        
-    vtfile=$1; vtskip=$2; vtmagic=$3; vttmp=$4    
-    echo "=====ventoy_unpack_initramfs: #$*#" >> $VTLOG
-    
-    #special process
-    #if [ "${vtmagic:0:4}" = '5678' ]; then
-    #    echo -en '\x1F\x8B' | dd status=none of=$vtfile bs=1 count=2 conv=notrunc
-    #    vtmagic='1F8B'
-    #fi
-    
-    if [ "${vtmagic:0:4}" = '6873' ]; then
-        ventoy_mount_squashfs $vtfile
-        return
-    fi
-    
-    for vtx in '1F8B zcat' '1F9E zcat' '425A bzcat' '5D00 lzcat' 'FD37 xzcat' '894C lzopcat' '0221 lz4cat' '28B5 zstdcat' '3037 cat'; do
-        if [ "${vtx:0:4}" = "${vtmagic:0:4}" ]; then
-            echo "vtx=$vtx" >> $VTLOG            
-            if [ $vtskip -eq 0 ]; then            
-                if [ "${vtx:5}" = "xzcat" ]; then
-                    rm -f $VTOY_PATH/xzlog
-                    ${vtx:5} $vtfile 2> $VTOY_PATH/xzlog | (cpio -idmu 2>>$VTLOG; cat > $vttmp)
-                    
-                    if grep -q 'corrupted data' $VTOY_PATH/xzlog; then
-                        echo 'xzcat failed, now try xzminidec...' >> $VTLOG        
-                        cat $vtfile | xzminidec | (cpio -idmu 2>>$VTLOG; cat > $vttmp)
-                    fi
-                    
-                else
-                    ${vtx:5} $vtfile | (cpio -idmu 2>>$VTLOG; cat > $vttmp)
-                fi
-            else
-                dd if=$vtfile skip=$vtskip iflag=skip_bytes status=none | ${vtx:5} | (cpio -idmu 2>>$VTLOG; cat > $vttmp)
-            fi
-            break
-        fi
-    done
-}
-
-# param: file magic tmp
-ventoy_unpack_initrd() {        
-    vtfile=$1; vtmagic=$2; vttmp=$3    
-    echo "=====ventoy_unpack_initrd: #$*#" >> $VTLOG
-    
-    for vtx in '1F8B zcat' '1F9E zcat' '425A bzcat' '5D00 lzcat' 'FD37 xzcat' '894C lzopcat' '0221 lz4cat' '28B5 zstdcat' '3037 cat'; do
-        if [ "${vtx:0:4}" = "${vtmagic:0:4}" ]; then
-            echo "vtx=$vtx" >> $VTLOG            
-            ${vtx:5} $vtfile > $vttmp
-            break
-        fi
-    done    
-}
-
-
-# This export is for busybox cpio command
-export EXTRACT_UNSAFE_SYMLINKS=1
-
-for vtfile in $(ls /initrd*); do    
-    #decompress first initrd
-    vtmagic=$(hexdump -n 2 -e '2/1 "%02X"' $vtfile)
-
-    if ventoy_is_initrd_ramdisk; then
-        ventoy_unpack_initrd $vtfile $vtmagic ${vtfile}_tmp
-        mv ${vtfile}_tmp $vtfile
-        break
-    else
-        ventoy_unpack_initramfs $vtfile 0 $vtmagic ${vtfile}_tmp
-    fi
-
-    #only for cpio,cpio,...,initrd sequence, initrd,cpio or initrd,initrd sequence is not supported
-    while [ -e ${vtfile}_tmp ] && [ $(stat -c '%s' ${vtfile}_tmp) -gt 512 ]; do
-        mv ${vtfile}_tmp $vtfile
-        vtdump=$(hexdump -n 512 -e '512/1 "%02X"' $vtfile)
-        vtmagic=$(echo $vtdump | sed 's/^\(00\)*//')
-        let vtoffset="(${#vtdump}-${#vtmagic})/2"
-        
-        if [ -z "$vtmagic" ]; then
-            echo "terminate with all zero data file" >> $VTLOG
-            break
-        fi
-        
-        ventoy_unpack_initramfs $vtfile $vtoffset ${vtmagic:0:4} ${vtfile}_tmp
-    done
-    
-    rm -f $vtfile ${vtfile}_tmp
-done
-
-
-#break here for debug
-if [ "$VTOY_BREAK_LEVEL" = "02" ] || [ "$VTOY_BREAK_LEVEL" = "12" ]; then
-    sleep 5
-    echo -e "\n\n\033[32m ################################################# \033[0m"
-    echo -e "\033[32m ################ VENTOY DEBUG ################### \033[0m"
-    echo -e "\033[32m ################################################# \033[0m \n"   
-    if [ "$VTOY_BREAK_LEVEL" = "12" ]; then 
-        cat $VTOY_PATH/log
-    fi    
-    exec $BUSYBOX_PATH/sh
-fi
-
-
-####################################################################
-#                                                                  #
-# Step 3 : Extract injection archive                               #
-#                                                                  #
-####################################################################
-ventoy_unpack_injection() {
-    vtmagic=$(hexdump -n 2 -e '2/1 "%02X"' $VTOY_PATH/ventoy_injection)
-    echo "ventoy_unpack_injection  vtmagic=$vtmagic ..."
-    
-    if [ "1F8B" = "$vtmagic" ] || [ "1F9E" = "$vtmagic" ]; then
-        echo "tar.gz  tar -xzvf"
-        tar -xzvf $VTOY_PATH/ventoy_injection -C /
-    elif [ "425A" = "$vtmagic" ]; then
-        echo "tar.bz2  tar -xjvf"
-        tar -xjvf $VTOY_PATH/ventoy_injection -C / 
-    elif [ "FD37" = "$vtmagic" ]; then
-        echo "tar.xz  tar -xJvf"
-        tar -xJvf $VTOY_PATH/ventoy_injection -C /
-    elif [ "5D00" = "$vtmagic" ]; then
-        echo "tar.lzma  tar -xavf"
-        tar -xavf $VTOY_PATH/ventoy_injection -C /
-    else
-        echo "unzip -o"
-        unzip -o $VTOY_PATH/ventoy_injection -d /
-    fi
-}
-
-if [ -e $VTOY_PATH/ventoy_injection ]; then
-    echo "### decompress injection ... ###" >>$VTLOG
-    ventoy_unpack_injection > $VTOY_PATH/injection.log 2>&1
+    echo "handover to init_chain" >>$VTLOG
+    exec $BUSYBOX_PATH/sh $VTOY_PATH/init_chain
 fi
-
-
-####################################################################
-#                                                                  #
-# Step 4 : Hand over to ventoy.sh                                  #
-#                                                                  #
-####################################################################
-echo "Now hand over to ventoy.sh" >>$VTLOG
-. $VTOY_PATH/tool/vtoytool_install.sh
-
-export PATH=$VTOY_ORG_PATH
-exec $BUSYBOX_PATH/sh $VTOY_PATH/ventoy.sh
diff --git a/IMG/cpio/ventoy/init_chain b/IMG/cpio/ventoy/init_chain
new file mode 100644 (file)
index 0000000..17e27c7
--- /dev/null
@@ -0,0 +1,226 @@
+#!/ventoy/busybox/sh
+#************************************************************************************
+# Copyright (c) 2020, longpanda <admin@ventoy.net>
+# 
+# This program 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.
+# 
+# This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+# 
+#************************************************************************************
+
+
+###################################################################
+#                                                                  #
+# Step 1 : parse kernel debug parameter                            #
+#                                                                  #
+####################################################################
+[ -d /proc ] || mkdir /proc; mount -t proc proc /proc
+vtcmdline=$(cat /proc/cmdline)
+vtkerver=$(cat /proc/version)
+umount /proc; rm -rf /proc
+
+echo "kenel version=$vtkerver" >>$VTLOG
+echo "kenel cmdline=$vtcmdline" >>$VTLOG
+
+#break here for debug
+if [ "$VTOY_BREAK_LEVEL" = "01" ] || [ "$VTOY_BREAK_LEVEL" = "11" ]; then
+    sleep 5
+    echo -e "\n\n\033[32m ################################################# \033[0m"
+    echo -e "\033[32m ################ VENTOY DEBUG ################### \033[0m"
+    echo -e "\033[32m ################################################# \033[0m \n"
+    
+    if [ "$VTOY_BREAK_LEVEL" = "11" ]; then
+        cat $VTLOG
+    fi
+    exec $BUSYBOX_PATH/sh
+fi
+
+
+####################################################################
+#                                                                  #
+# Step 2 : extract real initramfs to /                             #
+#                                                                  #
+####################################################################
+cd /
+rm -rf /init /linuxrc /dev/  /root
+
+vtSbinFileNum=$(ls -1 /sbin | wc -l)
+if [ $vtSbinFileNum -eq 1 ]; then
+    echo "remove whole sbin directory" >> $VTLOG
+    rm -rf /sbin
+else
+    echo "remove only sbin/init file" >> $VTLOG
+    ls -l /sbin >> $VTLOG
+    rm -f /sbin/init
+fi
+
+ventoy_is_initrd_ramdisk() {
+    #As I known, PCLinuxOS use ramdisk
+    if echo $vtkerver | grep -i -q 'PCLinuxOS'; then
+        true
+    else
+        false
+    fi
+}
+
+ventoy_mount_squashfs() {
+    mkdir /dev
+    mount -t devtmpfs devtmpfs /dev    
+    dd if=$1 of=/dev/ram0 status=none
+    umount /dev && rm -rf /dev
+}
+
+# param: file skip magic tmp
+ventoy_unpack_initramfs() {        
+    vtfile=$1; vtskip=$2; vtmagic=$3; vttmp=$4    
+    echo "=====ventoy_unpack_initramfs: #$*#" >> $VTLOG
+    
+    #special process
+    #if [ "${vtmagic:0:4}" = '5678' ]; then
+    #    echo -en '\x1F\x8B' | dd status=none of=$vtfile bs=1 count=2 conv=notrunc
+    #    vtmagic='1F8B'
+    #fi
+    
+    if [ "${vtmagic:0:4}" = '6873' ]; then
+        ventoy_mount_squashfs $vtfile
+        return
+    fi
+    
+    for vtx in '1F8B zcat' '1F9E zcat' '425A bzcat' '5D00 lzcat' 'FD37 xzcat' '894C lzopcat' '0221 lz4cat' '28B5 zstdcat' '3037 cat'; do
+        if [ "${vtx:0:4}" = "${vtmagic:0:4}" ]; then
+            echo "vtx=$vtx" >> $VTLOG            
+            if [ $vtskip -eq 0 ]; then            
+                if [ "${vtx:5}" = "xzcat" ]; then
+                    rm -f $VTOY_PATH/xzlog
+                    ${vtx:5} $vtfile 2> $VTOY_PATH/xzlog | (cpio -idmu 2>>$VTLOG; cat > $vttmp)
+                    
+                    if grep -q 'corrupted data' $VTOY_PATH/xzlog; then
+                        echo 'xzcat failed, now try xzminidec...' >> $VTLOG        
+                        cat $vtfile | xzminidec | (cpio -idmu 2>>$VTLOG; cat > $vttmp)
+                    fi
+                    
+                else
+                    ${vtx:5} $vtfile | (cpio -idmu 2>>$VTLOG; cat > $vttmp)
+                fi
+            else
+                dd if=$vtfile skip=$vtskip iflag=skip_bytes status=none | ${vtx:5} | (cpio -idmu 2>>$VTLOG; cat > $vttmp)
+            fi
+            break
+        fi
+    done
+}
+
+# param: file magic tmp
+ventoy_unpack_initrd() {        
+    vtfile=$1; vtmagic=$2; vttmp=$3    
+    echo "=====ventoy_unpack_initrd: #$*#" >> $VTLOG
+    
+    for vtx in '1F8B zcat' '1F9E zcat' '425A bzcat' '5D00 lzcat' 'FD37 xzcat' '894C lzopcat' '0221 lz4cat' '28B5 zstdcat' '3037 cat'; do
+        if [ "${vtx:0:4}" = "${vtmagic:0:4}" ]; then
+            echo "vtx=$vtx" >> $VTLOG            
+            ${vtx:5} $vtfile > $vttmp
+            break
+        fi
+    done    
+}
+
+
+# This export is for busybox cpio command
+export EXTRACT_UNSAFE_SYMLINKS=1
+
+for vtfile in $(ls /initrd*); do    
+    #decompress first initrd
+    vtmagic=$(hexdump -n 2 -e '2/1 "%02X"' $vtfile)
+
+    if ventoy_is_initrd_ramdisk; then
+        ventoy_unpack_initrd $vtfile $vtmagic ${vtfile}_tmp
+        mv ${vtfile}_tmp $vtfile
+        break
+    else
+        ventoy_unpack_initramfs $vtfile 0 $vtmagic ${vtfile}_tmp
+    fi
+
+    #only for cpio,cpio,...,initrd sequence, initrd,cpio or initrd,initrd sequence is not supported
+    while [ -e ${vtfile}_tmp ] && [ $(stat -c '%s' ${vtfile}_tmp) -gt 512 ]; do
+        mv ${vtfile}_tmp $vtfile
+        vtdump=$(hexdump -n 512 -e '512/1 "%02X"' $vtfile)
+        vtmagic=$(echo $vtdump | sed 's/^\(00\)*//')
+        let vtoffset="(${#vtdump}-${#vtmagic})/2"
+        
+        if [ -z "$vtmagic" ]; then
+            echo "terminate with all zero data file" >> $VTLOG
+            break
+        fi
+        
+        ventoy_unpack_initramfs $vtfile $vtoffset ${vtmagic:0:4} ${vtfile}_tmp
+    done
+    
+    rm -f $vtfile ${vtfile}_tmp
+done
+
+
+#break here for debug
+if [ "$VTOY_BREAK_LEVEL" = "02" ] || [ "$VTOY_BREAK_LEVEL" = "12" ]; then
+    sleep 5
+    echo -e "\n\n\033[32m ################################################# \033[0m"
+    echo -e "\033[32m ################ VENTOY DEBUG ################### \033[0m"
+    echo -e "\033[32m ################################################# \033[0m \n"   
+    if [ "$VTOY_BREAK_LEVEL" = "12" ]; then 
+        cat $VTOY_PATH/log
+    fi    
+    exec $BUSYBOX_PATH/sh
+fi
+
+
+####################################################################
+#                                                                  #
+# Step 3 : Extract injection archive                               #
+#                                                                  #
+####################################################################
+ventoy_unpack_injection() {
+    vtmagic=$(hexdump -n 2 -e '2/1 "%02X"' $VTOY_PATH/ventoy_injection)
+    echo "ventoy_unpack_injection  vtmagic=$vtmagic ..."
+    
+    if [ "1F8B" = "$vtmagic" ] || [ "1F9E" = "$vtmagic" ]; then
+        echo "tar.gz  tar -xzvf"
+        tar -xzvf $VTOY_PATH/ventoy_injection -C /
+    elif [ "425A" = "$vtmagic" ]; then
+        echo "tar.bz2  tar -xjvf"
+        tar -xjvf $VTOY_PATH/ventoy_injection -C / 
+    elif [ "FD37" = "$vtmagic" ]; then
+        echo "tar.xz  tar -xJvf"
+        tar -xJvf $VTOY_PATH/ventoy_injection -C /
+    elif [ "5D00" = "$vtmagic" ]; then
+        echo "tar.lzma  tar -xavf"
+        tar -xavf $VTOY_PATH/ventoy_injection -C /
+    else
+        echo "unzip -o"
+        unzip -o $VTOY_PATH/ventoy_injection -d /
+    fi
+}
+
+if [ -e $VTOY_PATH/ventoy_injection ]; then
+    echo "### decompress injection ... ###" >>$VTLOG
+    ventoy_unpack_injection > $VTOY_PATH/injection.log 2>&1
+fi
+
+
+####################################################################
+#                                                                  #
+# Step 4 : Hand over to ventoy_chain.sh                                  #
+#                                                                  #
+####################################################################
+echo "Now hand over to ventoy.sh" >>$VTLOG
+. $VTOY_PATH/tool/vtoytool_install.sh
+
+export PATH=$VTOY_ORG_PATH
+exec $BUSYBOX_PATH/sh $VTOY_PATH/ventoy_chain.sh
diff --git a/IMG/cpio/ventoy/init_loop b/IMG/cpio/ventoy/init_loop
new file mode 100644 (file)
index 0000000..1cbb619
--- /dev/null
@@ -0,0 +1,90 @@
+#!/ventoy/busybox/sh
+#************************************************************************************
+# Copyright (c) 2020, longpanda <admin@ventoy.net>
+# 
+# This program 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.
+# 
+# This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+# 
+#************************************************************************************
+
+
+###################################################################
+#                                                                  #
+# Step 1 : parse kernel debug parameter                            #
+#                                                                  #
+####################################################################
+[ -d /proc ] || mkdir /proc; mount -t proc proc /proc
+vtcmdline=$(cat /proc/cmdline)
+vtkerver=$(cat /proc/version)
+umount /proc; rm -rf /proc
+
+echo "kenel version=$vtkerver" >>$VTLOG
+echo "kenel cmdline=$vtcmdline" >>$VTLOG
+
+#break here for debug
+if [ "$VTOY_BREAK_LEVEL" = "01" ] || [ "$VTOY_BREAK_LEVEL" = "11" ]; then
+    sleep 5
+    echo -e "\n\n\033[32m ################################################# \033[0m"
+    echo -e "\033[32m ################ VENTOY DEBUG ################### \033[0m"
+    echo -e "\033[32m ################################################# \033[0m \n"
+    
+    if [ "$VTOY_BREAK_LEVEL" = "11" ]; then
+        cat $VTLOG
+    fi
+    exec $BUSYBOX_PATH/sh
+fi
+
+
+####################################################################
+#                                                                  #
+# Step 2 : Extract injection archive                               #
+#                                                                  #
+####################################################################
+ventoy_unpack_injection() {
+    vtmagic=$(hexdump -n 2 -e '2/1 "%02X"' $VTOY_PATH/ventoy_injection)
+    echo "ventoy_unpack_injection  vtmagic=$vtmagic ..."
+    
+    if [ "1F8B" = "$vtmagic" ] || [ "1F9E" = "$vtmagic" ]; then
+        echo "tar.gz  tar -xzvf"
+        tar -xzvf $VTOY_PATH/ventoy_injection -C /
+    elif [ "425A" = "$vtmagic" ]; then
+        echo "tar.bz2  tar -xjvf"
+        tar -xjvf $VTOY_PATH/ventoy_injection -C / 
+    elif [ "FD37" = "$vtmagic" ]; then
+        echo "tar.xz  tar -xJvf"
+        tar -xJvf $VTOY_PATH/ventoy_injection -C /
+    elif [ "5D00" = "$vtmagic" ]; then
+        echo "tar.lzma  tar -xavf"
+        tar -xavf $VTOY_PATH/ventoy_injection -C /
+    else
+        echo "unzip -o"
+        unzip -o $VTOY_PATH/ventoy_injection -d /
+    fi
+}
+
+if [ -e $VTOY_PATH/ventoy_injection ]; then
+    echo "### decompress injection ... ###" >>$VTLOG
+    ventoy_unpack_injection > $VTOY_PATH/injection.log 2>&1
+fi
+
+
+####################################################################
+#                                                                  #
+# Step 3 : Hand over to ventoy_loop.sh                                  #
+#                                                                  #
+####################################################################
+echo "Now hand over to ventoy.sh" >>$VTLOG
+. $VTOY_PATH/tool/vtoytool_install.sh
+
+export PATH=$VTOY_ORG_PATH
+exec $BUSYBOX_PATH/sh $VTOY_PATH/ventoy_loop.sh
diff --git a/IMG/cpio/ventoy/loop/deepin/ventoy-disk.sh b/IMG/cpio/ventoy/loop/deepin/ventoy-disk.sh
new file mode 100644 (file)
index 0000000..48c3752
--- /dev/null
@@ -0,0 +1,36 @@
+#!/bin/sh
+#************************************************************************************
+# Copyright (c) 2020, longpanda <admin@ventoy.net>
+# 
+# This program 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.
+# 
+# This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+# 
+#************************************************************************************
+
+cd /ventoy
+xzcat tool.cpio.xz | cpio -idmu
+/ventoy/tool/vtoytool/00/vtoytool_64 --install
+
+while [ -n "Y" ]; do   
+    line=$(/ventoy/tool/vtoydump -f /ventoy/ventoy_os_param)
+    if [ $? -eq 0 ]; then
+        vtdiskname=${line%%#*}
+        break
+    else    
+        sleep 1
+    fi
+done
+
+echo "ventoy disk is $vtdiskname" >> /ventoy/log
+/ventoy/tool/vtoydm -p -f /ventoy/ventoy_image_map -d $vtdiskname > /ventoy/ventoy_dm_table
+dmsetup create ventoy /ventoy/ventoy_dm_table --readonly
diff --git a/IMG/cpio/ventoy/loop/deepin/ventoy-init.sh b/IMG/cpio/ventoy/loop/deepin/ventoy-init.sh
new file mode 100644 (file)
index 0000000..17543eb
--- /dev/null
@@ -0,0 +1,21 @@
+#!/bin/sh
+#************************************************************************************
+# Copyright (c) 2020, longpanda <admin@ventoy.net>
+# 
+# This program 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.
+# 
+# This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+# 
+#************************************************************************************
+
+sed "/^mountroot$/i\\sh /ventoy/loop/deepin/ventoy-disk.sh" -i /init
+exec /init
diff --git a/IMG/cpio/ventoy/loop/endless/ventoy-hook.sh b/IMG/cpio/ventoy/loop/endless/ventoy-hook.sh
new file mode 100644 (file)
index 0000000..7d0820d
--- /dev/null
@@ -0,0 +1,36 @@
+#!/ventoy/busybox/sh
+#************************************************************************************
+# Copyright (c) 2020, longpanda <admin@ventoy.net>
+# 
+# This program 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.
+# 
+# This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+# 
+#************************************************************************************
+
+. $VTOY_PATH/hook/ventoy-os-lib.sh
+
+END_UDEV_DIR=$(ventoy_get_udev_conf_dir)
+
+if ! [ -e "$END_UDEV_DIR/10-dm.rules" ]; then
+    echo 'Copy dm rule file' >> $VTLOG
+    $CAT $VTOY_PATH/hook/default/10-dm.rules > "$END_UDEV_DIR/10-dm.rules"
+fi
+
+if ! [ -e "$END_UDEV_DIR/13-dm-disk.rules" ]; then
+    echo 'Copy dm-disk rule file' >> $VTLOG
+    $CAT $VTOY_PATH/hook/default/13-dm-disk.rules > "$END_UDEV_DIR/13-dm-disk.rules"
+fi
+
+ventoy_set_loop_inotify_script  endless/ventoy-inotifyd-hook.sh
+$BUSYBOX_PATH/cp -a $VTOY_PATH/loop/endless/ventoy-inotifyd-start.sh /lib/dracut/hooks/pre-udev/01-ventoy-inotifyd-start.sh
+
diff --git a/IMG/cpio/ventoy/loop/endless/ventoy-inotifyd-hook.sh b/IMG/cpio/ventoy/loop/endless/ventoy-inotifyd-hook.sh
new file mode 100644 (file)
index 0000000..cc9050d
--- /dev/null
@@ -0,0 +1,37 @@
+#!/ventoy/busybox/sh
+#************************************************************************************
+# Copyright (c) 2020, longpanda <admin@ventoy.net>
+# 
+# This program 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.
+# 
+# This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+# 
+#************************************************************************************
+
+. /ventoy/hook/ventoy-hook-lib.sh
+
+if is_ventoy_hook_finished; then
+    exit 0
+fi
+
+VTPATH_OLD=$PATH; PATH=$PATH:$BUSYBOX_PATH:$VTOY_PATH/tool
+
+if is_inotify_ventoy_part $3; then
+    vtlog "##### INOTIFYD: $2/$3 is created (YES) ..."
+
+    ventoy_udev_disk_common_hook "$3" "noreplace"
+    set_ventoy_hook_finish
+else
+    vtlog "##### INOTIFYD: $2/$3 is created (NO) ..."
+fi
+
+PATH=$VTPATH_OLD
diff --git a/IMG/cpio/ventoy/loop/endless/ventoy-inotifyd-start.sh b/IMG/cpio/ventoy/loop/endless/ventoy-inotifyd-start.sh
new file mode 100644 (file)
index 0000000..6375dc5
--- /dev/null
@@ -0,0 +1,31 @@
+#!/ventoy/busybox/sh
+#************************************************************************************
+# Copyright (c) 2020, longpanda <admin@ventoy.net>
+# 
+# This program 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.
+# 
+# This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+# 
+#************************************************************************************
+
+. /ventoy/hook/ventoy-hook-lib.sh
+
+vtHook=$($CAT $VTOY_PATH/inotifyd-loop-script.txt)
+
+vtdisk=$(get_ventoy_disk_name)
+if [ "$vtdisk" = "unknown" ]; then
+    vtlog "... start inotifyd listen $vtHook ..."
+    $BUSYBOX_PATH/nohup $VTOY_PATH/tool/inotifyd $vtHook  /dev:n  2>&-  & 
+else
+    vtlog "... $vtdisk already exist ..."
+    $BUSYBOX_PATH/sh $vtHook n /dev "${vtdisk#/dev/}2"
+fi
similarity index 99%
rename from IMG/cpio/ventoy/ventoy.sh
rename to IMG/cpio/ventoy/ventoy_chain.sh
index c1cc897ead7636a4eb8eb3d16c95b4af57f5218d..2c52e60e4626a93f82e74dec80049a94b3070319 100644 (file)
@@ -136,6 +136,8 @@ ventoy_get_os_type() {
             echo 'suse'; return        
         elif $GREP -q 'uruk' /etc/os-release; then
             echo 'debian'; return
+        elif $GREP -q 'Solus' /etc/os-release; then
+            echo 'rhel7'; return
         fi
     fi
     
diff --git a/IMG/cpio/ventoy/ventoy_loop.sh b/IMG/cpio/ventoy/ventoy_loop.sh
new file mode 100644 (file)
index 0000000..6171adf
--- /dev/null
@@ -0,0 +1,116 @@
+#!/ventoy/busybox/sh
+#************************************************************************************
+# Copyright (c) 2020, longpanda <admin@ventoy.net>
+# 
+# This program 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.
+# 
+# This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+# 
+#************************************************************************************
+
+####################################################################
+#                                                                  #
+# Step 1 : Parse kernel parameter                                  #
+#                                                                  #
+####################################################################
+if ! [ -e /proc ]; then
+    $BUSYBOX_PATH/mkdir /proc
+    rmproc='Y'
+fi
+$BUSYBOX_PATH/mount -t proc proc /proc
+
+# vtinit=xxx to replace rdinit=xxx
+vtcmdline=$($CAT /proc/cmdline)
+for i in $vtcmdline; do
+    if echo $i | $GREP -q vtinit; then
+        user_rdinit=${i#vtinit=}
+        echo "user set user_rdinit=${user_rdinit}" >>$VTLOG
+    fi
+done
+
+
+####################################################################
+#                                                                  #
+# Step 2 : Do OS specific hook                                     #
+#                                                                  #
+####################################################################
+ventoy_get_os_type() {
+    echo "kernel version" >> $VTLOG
+    $CAT /proc/version >> $VTLOG
+
+    # deepin-live
+    if $GREP -q 'deepin' /proc/version; then
+        echo 'deepin'; return
+    fi
+    
+    if $GREP -q 'endless' /proc/version; then
+        echo 'endless'; return
+    fi
+    
+    echo "default"
+}
+
+VTOS=$(ventoy_get_os_type)
+echo "OS=###${VTOS}###" >>$VTLOG
+if [ -e "$VTOY_PATH/loop/$VTOS/ventoy-hook.sh" ]; then
+    $BUSYBOX_PATH/sh "$VTOY_PATH/loop/$VTOS/ventoy-hook.sh"
+fi
+
+
+####################################################################
+#                                                                  #
+# Step 3 : Check for debug break                                   #
+#                                                                  #
+####################################################################
+if [ "$VTOY_BREAK_LEVEL" = "03" ] || [ "$VTOY_BREAK_LEVEL" = "13" ]; then
+    $SLEEP 5
+    echo -e "\n\n\033[32m ################################################# \033[0m"
+    echo -e "\033[32m ################ VENTOY DEBUG ################### \033[0m"
+    echo -e "\033[32m ################################################# \033[0m \n"
+    if [ "$VTOY_BREAK_LEVEL" = "13" ]; then 
+        $CAT $VTOY_PATH/log
+    fi
+    exec $BUSYBOX_PATH/sh
+fi
+
+
+####################################################################
+#                                                                  #
+# Step 3 : Hand over to real init                                  #
+#                                                                  #
+####################################################################
+$BUSYBOX_PATH/umount /proc
+if [ "$rmproc" = "Y" ]; then
+    $BUSYBOX_PATH/rm -rf /proc
+fi
+
+cd /
+
+unset VTLOG FIND GREP EGREP CAT AWK SED SLEEP HEAD
+
+for vtinit in $user_rdinit /sbin/init /init /linuxrc; do
+    if [ -d /ventoy_rdroot ]; then
+        if [ -e "/ventoy_rdroot$vtinit" ]; then
+            # switch_root will check /init file, this is a cheat code
+            echo 'switch_root' > /init
+            exec $BUSYBOX_PATH/switch_root /ventoy_rdroot "$vtinit"
+        fi
+    else
+        if [ -e "$vtinit" ];then
+            exec "$vtinit"
+        fi
+    fi
+done
+
+# Should never reach here
+echo -e "\n\n\033[31m ############ INIT NOT FOUND ############### \033[0m \n"
+exec $BUSYBOX_PATH/sh
index c288ed94d13fd8565778840ba40f1db202925c6b..301d7ccae3ef3751e5852b79afce92b29924b8b9 100644 (file)
@@ -28,7 +28,8 @@ find ./tool | cpio  -o -H newc>tool.cpio
 xz tool.cpio
 rm -rf tool
 
-xz ventoy.sh
+xz ventoy_chain.sh
+xz ventoy_loop.sh
 
 find ./hook | cpio  -o -H newc>hook.cpio
 xz hook.cpio
index 83f1e7e128113f8983a5b70a7b40abcd1962eccd..2e16ca51f00e743f4838f7b2a15dcbd73ed9d615 100644 (file)
@@ -62,12 +62,12 @@ else
 fi
 
 # 00->ff avoid sparse file
-dd if=/dev/zero  bs=1M count=$size | tr '\000' '\377' > persistence.img
+dd if=/dev/zero  bs=1M count=$size | tr '\000' '\377' > persistence.dat
 sync
 
 freeloop=$(losetup -f)
 
-losetup $freeloop persistence.img
+losetup $freeloop persistence.dat
 
 mkfs -t $fstype $fsopt -L $label $freeloop 
 
index b653327403e6504b08629d627fde8f2c5c6e7689..eb7a847189b08fabddf84cadd0d7cd1e263d3460 100644 (file)
Binary files a/INSTALL/EFI/BOOT/grubx64_real.efi and b/INSTALL/EFI/BOOT/grubx64_real.efi differ
index f2ea24f54729a6070af54daa71b0d0407f363f9f..d59e46d772fd2a09422dd1bd1b34e2a068247e9e 100644 (file)
 #************************************************************************************
 
 function ventoy_pause {
-    if [ -n "${vtdebug_flag}" ]; then
-        echo "press Enter to continue ......"
-        read vtTmpPause
-    fi
+    echo "press Enter to continue ......"
+    read vtTmpPause
 }
 
 function ventoy_debug_pause {
@@ -30,29 +28,20 @@ function ventoy_debug_pause {
     fi
 }
 
-function ventoy_cli_console {      
-    if [ "$grub_platform" = "pc" ]; then
-        #terminal_output  vga_text
+function ventoy_cli_console {
+    if [ -z "$vtoy_display_mode" ]; then
+        terminal_output  console
+    elif [ "$vtoy_display_mode" = "GUI" ]; then
         terminal_output  console
-    else
-        if [ "$vtoy_display_mode" != "CLI" ]; then
-            terminal_output  console
-        fi
     fi
 }
 
 function ventoy_gui_console {  
-    if [ "$grub_platform" = "pc" ]; then
-        if [ "$vtoy_display_mode" = "CLI" ]; then
-            terminal_output  console
-        else
-            terminal_output  gfxterm
-        fi
-    else
-        if [ "$vtoy_display_mode" != "CLI" ]; then
-            terminal_output  gfxterm
-        fi
-    fi
+    if [ -z "$vtoy_display_mode" ]; then
+        terminal_output  gfxterm
+    elif [ "$vtoy_display_mode" = "GUI" ]; then
+        terminal_output  gfxterm
+    fi    
 }
 
 function ventoy_power {
@@ -401,7 +390,7 @@ function uefi_linux_menu_func {
         fi
         
         vt_load_cpio  ${vtoy_path}/ventoy.cpio   $2 $1
-
+        
         vt_linux_clear_initrd
         
         if [ -d (loop)/pmagic ]; then
@@ -501,7 +490,7 @@ function uefi_iso_menu_func {
         unset LoadIsoEfiDriver
     fi
 
-    vt_chosen_img_path chosen_path
+    set chosen_path=$2
     vt_select_auto_install ${chosen_path}
     vt_select_persistence ${chosen_path}
 
@@ -512,8 +501,7 @@ function uefi_iso_menu_func {
         vt_iso9660_nojoliet 0
     fi
 
-    loopback loop ${1}${chosen_path}
-    vt_parse_iso_volume ${1}${chosen_path} vt_system_id vt_volume_id
+    loopback loop ${1}${chosen_path}    
     get_os_type (loop)
     
     if [ -d (loop)/EFI ]; then
@@ -548,10 +536,8 @@ function uefi_iso_menu_func {
 }
 
 function uefi_iso_memdisk {    
-    vt_chosen_img_path chosen_path
-
     echo 'Loading ISO file to memory ...'
-    vt_load_iso_to_mem ${1}${chosen_path} vtoy_iso_buf
+    vt_load_img_memdisk ${1}${2} vtoy_iso_buf
     
     ventoy_cli_console
     chainloader ${vtoy_path}/ventoy_x64.efi memdisk env_param=${env_param} isoefi=${LoadIsoEfiDriver} ${vtdebug_flag} mem:${vtoy_iso_buf_addr}:size:${vtoy_iso_buf_size}
@@ -679,7 +665,7 @@ function legacy_iso_menu_func {
         loopback -d loop
     fi
 
-    vt_chosen_img_path chosen_path
+    set chosen_path=$2
     vt_select_auto_install ${chosen_path}
     vt_select_persistence ${chosen_path}
 
@@ -691,7 +677,7 @@ function legacy_iso_menu_func {
     fi
     
     loopback loop ${1}${chosen_path}
-    vt_parse_iso_volume ${1}${chosen_path} vt_system_id vt_volume_id
+    
     get_os_type (loop)
 
     if [ -n "$vtcompat" ]; then
@@ -716,29 +702,99 @@ function legacy_iso_menu_func {
 }
 
 function legacy_iso_memdisk {
-    vt_chosen_img_path chosen_path
 
     linux16   $vtoy_path/memdisk iso raw    
     echo "Loading ISO file to memory ..."
-    initrd16  ${1}${chosen_path}
+    initrd16  ${1}${2}
+    boot
+}
+
+function iso_deepin_live_proc {
+    if [ -d (loop)/ ]; then
+        loopback -d loop
+    fi
+
+    loopback loop ${1}${2}   
+    vt_img_sector ${1}${2}
+
+    vt_load_cpio  $vtoy_path/ventoy.cpio  $2 $1   
+    vt_trailer_cpio $1 $2 noinit
+    
+    ventoy_debug_pause
+
+    vt_set_boot_opt rdinit=/ventoy/loop/deepin/ventoy-init.sh live-media=/dev/mapper/ventoy
+    
+    set ventoy_loading_tip="Loading files ......"
+    
+    linux (loop)/live/vmlinuz boot=live components locales=zh_CN.UTF-8 splash quiet
+    initrd (loop)/live/initrd.img
     boot
+    
+    unset ventoy_loading_tip
+    
+    vt_unset_boot_opt
+}
+
+
+function iso_endless_os_proc {
+    if [ -d (loop)/ ]; then
+        loopback -d loop
+    fi
+
+    loopback loop ${1}${2}   
+    vt_img_sector ${1}${2}
+
+    vt_load_cpio  $vtoy_path/ventoy.cpio  $2 $1   
+    vt_trailer_cpio $1 $2 noinit
+    
+    ventoy_debug_pause
+
+    vt_set_boot_opt '@kparams' rdinit=/vtoy/vtoy 
+
+    set eosimage=loop
+    set ventoy_bls_bootdev=/boot    
+    set ventoy_loading_tip="Loading files ......"
+    
+    export eosimage    
+    configfile (loop)/endless/grub/grub.cfg
+    
+    unset eosimage
+    unset ventoy_bls_bootdev
+    unset ventoy_loading_tip
+    
+    vt_unset_boot_opt
 }
 
 function iso_common_menuentry {
     unset vt_system_id
     unset vt_volume_id
     
+    vt_chosen_img_path vt_chosen_path vt_chosen_size
+    vt_parse_iso_volume ${vtoy_iso_part}${vt_chosen_path} vt_system_id vt_volume_id
+    
+    #special process for deepin-live iso
+    if [ "$vt_chosen_size" = "403701760" ]; then
+        if vt_str_begin $vt_chosen_path "/deepin-live"; then
+            iso_deepin_live_proc $vtoy_iso_part $vt_chosen_path
+        fi
+    fi
+
+    #special process for Endless OS
+    if vt_str_begin $vt_volume_id "Endless-OS"; then
+        iso_endless_os_proc $vtoy_iso_part $vt_chosen_path
+    fi
+
     if [ "$grub_platform" = "pc" ]; then
         if vt_check_mode 0; then
-            legacy_iso_memdisk $vtoy_iso_part
+            legacy_iso_memdisk $vtoy_iso_part $vt_chosen_path
         else
-            legacy_iso_menu_func $vtoy_iso_part
+            legacy_iso_menu_func $vtoy_iso_part $vt_chosen_path
         fi
     else
         if vt_check_mode 0; then
-            uefi_iso_memdisk $vtoy_iso_part 
+            uefi_iso_memdisk $vtoy_iso_part  $vt_chosen_path
         else
-            uefi_iso_menu_func $vtoy_iso_part                
+            uefi_iso_menu_func $vtoy_iso_part  $vt_chosen_path             
         fi
     fi      
 }
@@ -755,8 +811,8 @@ function iso_unsupport_menuentry {
 }
 
 function wim_common_menuentry {
-    vt_chosen_img_path chosen_path
-    vt_wim_chain_data ${vtoy_iso_part}${chosen_path}
+    vt_chosen_img_path vt_chosen_path vt_chosen_size
+    vt_wim_chain_data ${vtoy_iso_part}${vt_chosen_path}
     
     ventoy_debug_pause    
     
@@ -780,10 +836,14 @@ function wim_unsupport_menuentry {
 }
 
 function efi_common_menuentry {
-    vt_chosen_img_path chosen_path
+    vt_chosen_img_path vt_chosen_path vt_chosen_size
+    
+    vt_concat_efi_iso ${vtoy_iso_part}${vt_chosen_path} vtoy_iso_buf
+    
+    ventoy_debug_pause
     
     ventoy_cli_console    
-    chainloader ${vtoy_iso_part}${chosen_path}
+    chainloader ${vtoy_path}/ventoy_x64.efi memdisk env_param=${env_param} isoefi=on ${vtdebug_flag} mem:${vtoy_iso_buf_addr}:size:${vtoy_iso_buf_size}
     boot
     ventoy_gui_console
 }
@@ -794,6 +854,17 @@ function efi_unsupport_menuentry {
 
 
 
+
+
+function img_common_menuentry {
+
+    echo "To be implement"
+}
+
+function img_unsupport_menuentry {
+    common_unsupport_menuentry
+}
+
 #############################################################
 #############################################################
 #############################################################
@@ -892,6 +963,18 @@ fi
 
 if [ "$vtoy_display_mode" = "CLI" ]; then
     terminal_output  console
+elif [ "$vtoy_display_mode" = "serial" ]; then
+    if [ -n "$vtoy_serial_param" ]; then
+        serial $vtoy_serial_param
+    fi
+    terminal_input   serial
+    terminal_output  serial
+elif [ "$vtoy_display_mode" = "serial_console" ]; then
+    if [ -n "$vtoy_serial_param" ]; then
+        serial $vtoy_serial_param
+    fi
+    terminal_input   serial console
+    terminal_output  serial console    
 else    
     if [ -n "$vtoy_theme" ]; then
         set theme=$vtoy_theme
diff --git a/INSTALL/grub/i386-pc/blscfg.mod b/INSTALL/grub/i386-pc/blscfg.mod
new file mode 100644 (file)
index 0000000..8be0760
Binary files /dev/null and b/INSTALL/grub/i386-pc/blscfg.mod differ
index 774f3c5e0b2ca19d885772d88821dede834d2993..832cd8a7f8950bb6baa9eaf48671b146d8415fa1 100644 (file)
@@ -1,6 +1,8 @@
 *acpi: acpi
 *all_functional_test: functional_test
 *background_image: gfxterm_background
+*bls_import: blscfg
+*blscfg: blscfg
 *cat: cat
 *cpuid: cpuid
 *crc: hashsum
@@ -106,6 +108,7 @@ help: minicmd
 hexdump_random: random
 initrd16: linux16
 initrd: linux
+initrdefi: linux
 keymap: keylayouts
 kfreebsd_loadenv: bsd
 kfreebsd_module: bsd
@@ -122,6 +125,7 @@ legacy_password: legacycfg
 legacy_source: legacycfg
 linux16: linux16
 linux: linux
+linuxefi: linux
 list_trusted: pgp
 loadfont: font
 lsapm: lsapm
@@ -184,6 +188,8 @@ vbeinfo: videoinfo
 vbetest: videotest
 videoinfo: videoinfo
 videotest: videotest
+vt_set_boot_opt: linux
+vt_unset_boot_opt: linux
 write_byte: memrw
 write_dword: memrw
 write_word: memrw
index 7232ad16d3752f46c9fdb716cbe8fc61f2a551a0..27043b12ee37bd598a784b0f2a8eea258347b0f5 100644 (file)
Binary files a/INSTALL/grub/i386-pc/core.img and b/INSTALL/grub/i386-pc/core.img differ
index 850d9851be917a824ff9216623026c9bb387157e..b910f873dc2d21bd65738ec116f15aa16cd5bf08 100644 (file)
Binary files a/INSTALL/grub/i386-pc/legacycfg.mod and b/INSTALL/grub/i386-pc/legacycfg.mod differ
index 5c5d59f4fafdc428102d44383ee386d886f90f87..adc608524859987db1ff23e513b387f9ad45f2be 100644 (file)
@@ -96,6 +96,7 @@ bufio:
 usbserial_ftdi: serial usb usbserial_common
 legacy_password_test: functional_test legacycfg
 cpuid: extcmd
+blscfg: extcmd normal
 hdparm: extcmd hexdump
 bfs: fshelp
 gcry_blowfish: crypto
diff --git a/INSTALL/grub/x86_64-efi/blscfg.mod b/INSTALL/grub/x86_64-efi/blscfg.mod
new file mode 100644 (file)
index 0000000..01c5479
Binary files /dev/null and b/INSTALL/grub/x86_64-efi/blscfg.mod differ
index 7239dd698d72642f1d3dcdb16787acaafd6a438f..c5429251fd2be70231f5f815b8bbbb643d569630 100644 (file)
@@ -1,6 +1,8 @@
 *acpi: acpi
 *all_functional_test: functional_test
 *background_image: gfxterm_background
+*bls_import: blscfg
+*blscfg: blscfg
 *cat: cat
 *cpuid: cpuid
 *crc: hashsum
@@ -96,6 +98,7 @@ help: minicmd
 hexdump_random: random
 initrd16: linux16
 initrd: linux
+initrdefi: linux
 keymap: keylayouts
 kfreebsd_loadenv: bsd
 kfreebsd_module: bsd
@@ -112,6 +115,7 @@ legacy_password: legacycfg
 legacy_source: legacycfg
 linux16: linux16
 linux: linux
+linuxefi: linux
 list_trusted: pgp
 loadbios: loadbios
 loadfont: font
@@ -173,6 +177,8 @@ true: true
 usb: usbtest
 videoinfo: videoinfo
 videotest: videotest
+vt_set_boot_opt: linux
+vt_unset_boot_opt: linux
 write_byte: memrw
 write_dword: memrw
 write_word: memrw
index 752af40fe6470b1b8c372add339b64f3e288fab9..91afa23917e56958eaf80c8a98a37f1136a4c848 100644 (file)
Binary files a/INSTALL/grub/x86_64-efi/legacycfg.mod and b/INSTALL/grub/x86_64-efi/legacycfg.mod differ
index fa072559b678adb408e8a53e5b315793e6202e45..fb1e9c1e5cfa905614c0099e15ce47cd8f406fb9 100644 (file)
@@ -93,6 +93,7 @@ bufio:
 usbserial_ftdi: serial usb usbserial_common
 legacy_password_test: functional_test legacycfg
 cpuid: extcmd
+blscfg: extcmd normal
 hdparm: extcmd hexdump
 bfs: fshelp
 gcry_blowfish: crypto
index d2c83bb1521428c0e3d38130619e0bf5b73ea788..a300aa4168c54fdad853126e291ef714bc0dbc6c 100644 (file)
Binary files a/INSTALL/grub/x86_64-efi/normal.mod and b/INSTALL/grub/x86_64-efi/normal.mod differ
index a6c4c460b48b361a18d60454bb18aaa84048fb7c..a6a97d4990c3781e94ab4c70c16e1758dffcd7b2 100644 (file)
Binary files a/INSTALL/ventoy/ventoy.cpio and b/INSTALL/ventoy/ventoy.cpio differ
diff --git a/INSTALL/ventoy/ventoy_efiboot.img.xz b/INSTALL/ventoy/ventoy_efiboot.img.xz
new file mode 100644 (file)
index 0000000..121ef3d
Binary files /dev/null and b/INSTALL/ventoy/ventoy_efiboot.img.xz differ
index df670586bdeb927041ea4439a14673c61118f274..ff342b6c40c205eac23fefd004099aeed9994853 100644 (file)
Binary files a/INSTALL/ventoy/ventoy_x64.efi and b/INSTALL/ventoy/ventoy_x64.efi differ