diff --git a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.c b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.c index bd28ca26..6cd64636 100644 --- a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.c +++ b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.c @@ -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 { diff --git a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.h b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.h index 2e2ab031..250da0ed 100644 --- a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.h +++ b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.h @@ -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; diff --git a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/VentoyProtocol.c b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/VentoyProtocol.c index 004c83f9..bb0e95e1 100644 --- a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/VentoyProtocol.c +++ b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/VentoyProtocol.c @@ -36,6 +36,7 @@ #include #include +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) { diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/Makefile.core.def b/GRUB2/MOD_SRC/grub-2.04/grub-core/Makefile.core.def index e8d4a7f4..4ac0746f 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/Makefile.core.def +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/Makefile.core.def @@ -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 index 00000000..55ee2be0 --- /dev/null +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/commands/blscfg.c @@ -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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +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 index 00000000..891eac5a --- /dev/null +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/commands/legacycfg.c @@ -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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 index 00000000..163b9a09 --- /dev/null +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/commands/loadenv.c @@ -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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 index 00000000..952f4612 --- /dev/null +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/commands/loadenv.h @@ -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 . + */ + +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 index 00000000..9faf2be0 --- /dev/null +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/commands/menuentry.c @@ -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 . + */ + +#include +#include +#include +#include +#include +#include +#include + +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); +} diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/kern/main.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/kern/main.c index 2f22ecb5..42bc22f7 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/kern/main.c +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/kern/main.c @@ -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 index 00000000..6601d5de --- /dev/null +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/loader/i386/linux.c @@ -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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +#ifdef GRUB_MACHINE_PCBIOS +#include +#endif + +#ifdef GRUB_MACHINE_EFI +#include +#define HAS_VGA_TEXT 0 +#define DEFAULT_VIDEO_MODE "auto" +#define ACCEPTS_PURE_TEXT 0 +#elif defined (GRUB_MACHINE_IEEE1275) +#include +#define HAS_VGA_TEXT 0 +#define DEFAULT_VIDEO_MODE "text" +#define ACCEPTS_PURE_TEXT 1 +#else +#include +#include +#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 index 00000000..bc29d3be --- /dev/null +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/normal/main.c @@ -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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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); +} diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/normal/menu.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/normal/menu.c index e5d8b88c..070f6d20 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/normal/menu.c +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/normal/menu.c @@ -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; diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/normal/menu_text.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/normal/menu_text.c index cb1d3d61..cd96ceb1 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/normal/menu_text.c +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/normal/menu_text.c @@ -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; diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy.c index 2995bd30..e10751f9 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy.c +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy.c @@ -34,6 +34,7 @@ #include #include #include +#include #ifdef GRUB_MACHINE_EFI #include #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 }, + }; diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_def.h b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_def.h index 75c22215..a514f6b5 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_def.h +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_def.h @@ -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, ...); diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_linux.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_linux.c index ad871a10..dfda6a84 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_linux.c +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_linux.c @@ -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) { diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_plugin.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_plugin.c index 7fbe9db7..426e75fc 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_plugin.c +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_plugin.c @@ -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 index 00000000..1e81309c --- /dev/null +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_unix.c @@ -0,0 +1,631 @@ +/****************************************************************************** + * ventoy_unix.c + * + * Copyright (c) 2020, longpanda + * + * 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 . + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 index 00000000..9859ff4c --- /dev/null +++ b/GRUB2/MOD_SRC/grub-2.04/include/grub/compiler.h @@ -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 . + */ + +#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 index 00000000..55c1c128 --- /dev/null +++ b/GRUB2/MOD_SRC/grub-2.04/include/grub/kernel.h @@ -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 . + */ + +#ifndef GRUB_KERNEL_HEADER +#define GRUB_KERNEL_HEADER 1 + +#include +#include + +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 index 00000000..0acdc2aa --- /dev/null +++ b/GRUB2/MOD_SRC/grub-2.04/include/grub/menu.h @@ -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 . + */ + +#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 index 00000000..8839ad85 --- /dev/null +++ b/GRUB2/MOD_SRC/grub-2.04/include/grub/normal.h @@ -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 . + */ + +#ifndef GRUB_NORMAL_HEADER +#define GRUB_NORMAL_HEADER 1 + +#include +#include +#include +#include +#include +#include +#include + +/* 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 */ diff --git a/IMG/cpio/sbin/init b/IMG/cpio/sbin/init index ef7b5d6d..bd8e06db 100644 --- a/IMG/cpio/sbin/init +++ b/IMG/cpio/sbin/init @@ -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 index 00000000..f33df582 --- /dev/null +++ b/IMG/cpio/ventoy/hook/default/10-dm.rules @@ -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-.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//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 > /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" diff --git a/IMG/cpio/ventoy/hook/ventoy-hook-lib.sh b/IMG/cpio/ventoy/hook/ventoy-hook-lib.sh index c656c6fe..2da5f079 100644 --- a/IMG/cpio/ventoy/hook/ventoy-hook-lib.sh +++ b/IMG/cpio/ventoy/hook/ventoy-hook-lib.sh @@ -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 diff --git a/IMG/cpio/ventoy/hook/ventoy-os-lib.sh b/IMG/cpio/ventoy/hook/ventoy-os-lib.sh index 05533347..fb36ac25 100644 --- a/IMG/cpio/ventoy/hook/ventoy-os-lib.sh +++ b/IMG/cpio/ventoy/hook/ventoy-os-lib.sh @@ -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 +} + + diff --git a/IMG/cpio/ventoy/init b/IMG/cpio/ventoy/init index ad5ac3a9..ef7310e6 100644 --- a/IMG/cpio/ventoy/init +++ b/IMG/cpio/ventoy/init @@ -24,203 +24,14 @@ # # #################################################################### [ -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 index 00000000..17e27c74 --- /dev/null +++ b/IMG/cpio/ventoy/init_chain @@ -0,0 +1,226 @@ +#!/ventoy/busybox/sh +#************************************************************************************ +# Copyright (c) 2020, longpanda +# +# 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 . +# +#************************************************************************************ + + +################################################################### +# # +# 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 index 00000000..1cbb6190 --- /dev/null +++ b/IMG/cpio/ventoy/init_loop @@ -0,0 +1,90 @@ +#!/ventoy/busybox/sh +#************************************************************************************ +# Copyright (c) 2020, longpanda +# +# 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 . +# +#************************************************************************************ + + +################################################################### +# # +# 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 index 00000000..48c3752d --- /dev/null +++ b/IMG/cpio/ventoy/loop/deepin/ventoy-disk.sh @@ -0,0 +1,36 @@ +#!/bin/sh +#************************************************************************************ +# Copyright (c) 2020, longpanda +# +# 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 . +# +#************************************************************************************ + +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 index 00000000..17543eb3 --- /dev/null +++ b/IMG/cpio/ventoy/loop/deepin/ventoy-init.sh @@ -0,0 +1,21 @@ +#!/bin/sh +#************************************************************************************ +# Copyright (c) 2020, longpanda +# +# 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 . +# +#************************************************************************************ + +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 index 00000000..7d0820d6 --- /dev/null +++ b/IMG/cpio/ventoy/loop/endless/ventoy-hook.sh @@ -0,0 +1,36 @@ +#!/ventoy/busybox/sh +#************************************************************************************ +# Copyright (c) 2020, longpanda +# +# 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 . +# +#************************************************************************************ + +. $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 index 00000000..cc9050da --- /dev/null +++ b/IMG/cpio/ventoy/loop/endless/ventoy-inotifyd-hook.sh @@ -0,0 +1,37 @@ +#!/ventoy/busybox/sh +#************************************************************************************ +# Copyright (c) 2020, longpanda +# +# 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 . +# +#************************************************************************************ + +. /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 index 00000000..6375dc5e --- /dev/null +++ b/IMG/cpio/ventoy/loop/endless/ventoy-inotifyd-start.sh @@ -0,0 +1,31 @@ +#!/ventoy/busybox/sh +#************************************************************************************ +# Copyright (c) 2020, longpanda +# +# 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 . +# +#************************************************************************************ + +. /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 diff --git a/IMG/cpio/ventoy/ventoy.sh b/IMG/cpio/ventoy/ventoy_chain.sh similarity index 99% rename from IMG/cpio/ventoy/ventoy.sh rename to IMG/cpio/ventoy/ventoy_chain.sh index c1cc897e..2c52e60e 100644 --- a/IMG/cpio/ventoy/ventoy.sh +++ b/IMG/cpio/ventoy/ventoy_chain.sh @@ -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 index 00000000..6171adfe --- /dev/null +++ b/IMG/cpio/ventoy/ventoy_loop.sh @@ -0,0 +1,116 @@ +#!/ventoy/busybox/sh +#************************************************************************************ +# Copyright (c) 2020, longpanda +# +# 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 . +# +#************************************************************************************ + +#################################################################### +# # +# 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 diff --git a/IMG/mkcpio.sh b/IMG/mkcpio.sh index c288ed94..301d7cca 100644 --- a/IMG/mkcpio.sh +++ b/IMG/mkcpio.sh @@ -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 diff --git a/INSTALL/CreatePersistentImg.sh b/INSTALL/CreatePersistentImg.sh index 83f1e7e1..2e16ca51 100644 --- a/INSTALL/CreatePersistentImg.sh +++ b/INSTALL/CreatePersistentImg.sh @@ -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 diff --git a/INSTALL/EFI/BOOT/grubx64_real.efi b/INSTALL/EFI/BOOT/grubx64_real.efi index b6533274..eb7a8471 100644 Binary files a/INSTALL/EFI/BOOT/grubx64_real.efi and b/INSTALL/EFI/BOOT/grubx64_real.efi differ diff --git a/INSTALL/grub/grub.cfg b/INSTALL/grub/grub.cfg index f2ea24f5..d59e46d7 100644 --- a/INSTALL/grub/grub.cfg +++ b/INSTALL/grub/grub.cfg @@ -17,10 +17,8 @@ #************************************************************************************ 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 index 00000000..8be07603 Binary files /dev/null and b/INSTALL/grub/i386-pc/blscfg.mod differ diff --git a/INSTALL/grub/i386-pc/command.lst b/INSTALL/grub/i386-pc/command.lst index 774f3c5e..832cd8a7 100644 --- a/INSTALL/grub/i386-pc/command.lst +++ b/INSTALL/grub/i386-pc/command.lst @@ -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 diff --git a/INSTALL/grub/i386-pc/core.img b/INSTALL/grub/i386-pc/core.img index 7232ad16..27043b12 100644 Binary files a/INSTALL/grub/i386-pc/core.img and b/INSTALL/grub/i386-pc/core.img differ diff --git a/INSTALL/grub/i386-pc/legacycfg.mod b/INSTALL/grub/i386-pc/legacycfg.mod index 850d9851..b910f873 100644 Binary files a/INSTALL/grub/i386-pc/legacycfg.mod and b/INSTALL/grub/i386-pc/legacycfg.mod differ diff --git a/INSTALL/grub/i386-pc/moddep.lst b/INSTALL/grub/i386-pc/moddep.lst index 5c5d59f4..adc60852 100644 --- a/INSTALL/grub/i386-pc/moddep.lst +++ b/INSTALL/grub/i386-pc/moddep.lst @@ -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 index 00000000..01c54792 Binary files /dev/null and b/INSTALL/grub/x86_64-efi/blscfg.mod differ diff --git a/INSTALL/grub/x86_64-efi/command.lst b/INSTALL/grub/x86_64-efi/command.lst index 7239dd69..c5429251 100644 --- a/INSTALL/grub/x86_64-efi/command.lst +++ b/INSTALL/grub/x86_64-efi/command.lst @@ -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 diff --git a/INSTALL/grub/x86_64-efi/legacycfg.mod b/INSTALL/grub/x86_64-efi/legacycfg.mod index 752af40f..91afa239 100644 Binary files a/INSTALL/grub/x86_64-efi/legacycfg.mod and b/INSTALL/grub/x86_64-efi/legacycfg.mod differ diff --git a/INSTALL/grub/x86_64-efi/moddep.lst b/INSTALL/grub/x86_64-efi/moddep.lst index fa072559..fb1e9c1e 100644 --- a/INSTALL/grub/x86_64-efi/moddep.lst +++ b/INSTALL/grub/x86_64-efi/moddep.lst @@ -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 diff --git a/INSTALL/grub/x86_64-efi/normal.mod b/INSTALL/grub/x86_64-efi/normal.mod index d2c83bb1..a300aa41 100644 Binary files a/INSTALL/grub/x86_64-efi/normal.mod and b/INSTALL/grub/x86_64-efi/normal.mod differ diff --git a/INSTALL/ventoy/ventoy.cpio b/INSTALL/ventoy/ventoy.cpio index a6c4c460..a6a97d49 100644 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 index 00000000..121ef3d1 Binary files /dev/null and b/INSTALL/ventoy/ventoy_efiboot.img.xz differ diff --git a/INSTALL/ventoy/ventoy_x64.efi b/INSTALL/ventoy/ventoy_x64.efi index df670586..ff342b6c 100644 Binary files a/INSTALL/ventoy/ventoy_x64.efi and b/INSTALL/ventoy/ventoy_x64.efi differ