return Status;
}
+#if (VENTOY_DEVICE_WARN != 0)
+STATIC VOID ventoy_warn_invalid_device(VOID)
+{
+ STATIC BOOLEAN flag = FALSE;
+
+ if (flag)
+ {
+ return;
+ }
+
+ flag = TRUE;
+ gST->ConOut->ClearScreen(gST->ConOut);
+ gST->ConOut->OutputString(gST->ConOut, VTOY_WARNING L"\r\n");
+ gST->ConOut->OutputString(gST->ConOut, VTOY_WARNING L"\r\n");
+ gST->ConOut->OutputString(gST->ConOut, VTOY_WARNING L"\r\n\r\n\r\n");
+
+ gST->ConOut->OutputString(gST->ConOut, L"This is NOT a standard Ventoy device and is NOT officially supported.\r\n\r\n");
+ gST->ConOut->OutputString(gST->ConOut, L"You should follow the official instructions in https://www.ventoy.net\r\n");
+
+ gST->ConOut->OutputString(gST->ConOut, L"\r\n\r\nWill continue to boot after 15 seconds ...... ");
+
+ sleep(15);
+}
+#else
+STATIC VOID ventoy_warn_invalid_device(VOID)
+{
+
+}
+#endif
+
STATIC EFI_STATUS EFIAPI ventoy_load_image
(
IN EFI_HANDLE ImageHandle,
UINTN i = 0;
UINTN Count = 0;
UINT64 DiskSize = 0;
+ MBR_HEAD *pMBR = NULL;
UINT8 *pBuffer = NULL;
EFI_HANDLE *Handles;
EFI_STATUS Status = EFI_SUCCESS;
if (CompareMem(g_chain->os_param.vtoy_disk_guid, pBuffer + 0x180, 16) == 0)
{
+ pMBR = (MBR_HEAD *)pBuffer;
+ if (pMBR->PartTbl[0].FsFlag != 0xEE)
+ {
+ if (pMBR->PartTbl[0].StartSectorId != 2048 ||
+ pMBR->PartTbl[1].SectorCount != 65536 ||
+ pMBR->PartTbl[1].StartSectorId != pMBR->PartTbl[0].StartSectorId + pMBR->PartTbl[0].SectorCount)
+ {
+ debug("Failed to check disk part table");
+ ventoy_warn_invalid_device();
+ }
+ }
+
gBlockData.RawBlockIoHandle = Handles[i];
gBlockData.pRawBlockIo = pBlockIo;
gBS->OpenProtocol(Handles[i], &gEfiDevicePathProtocolGuid,
UINT32 old_cnt = 0;
UINTN size = 0;
UINT8 chksum = 0;
+ const char *pEnv = NULL;
CHAR16 *pPos = NULL;
CHAR16 *pCmdLine = NULL;
EFI_STATUS Status = EFI_SUCCESS;
}
pGrubParam = (ventoy_grub_param *)StrHexToUintn(pPos + StrLen(L"env_param="));
- grub_env_get = pGrubParam->grub_env_get;
grub_env_set = pGrubParam->grub_env_set;
+ grub_env_get = pGrubParam->grub_env_get;
+ pEnv = grub_env_get("VTOY_CHKDEV_RESULT_STRING");
+ if (!pEnv)
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (pEnv[0] != '0' || pEnv[1] != 0)
+ {
+ ventoy_warn_invalid_device();
+ }
+
g_file_replace_list = &pGrubParam->file_replace;
old_cnt = g_file_replace_list->old_file_cnt;
debug("file replace: magic:0x%x virtid:%u name count:%u <%a> <%a> <%a> <%a>",
gST->ConOut->ClearScreen(gST->ConOut);
ventoy_clear_input();
- ventoy_parse_cmdline(ImageHandle);
+ Status = ventoy_parse_cmdline(ImageHandle);
+ if (EFI_ERROR(Status))
+ {
+ return Status;
+ }
if (gMemdiskMode)
{
else
{
ventoy_save_variable();
- ventoy_find_iso_disk(ImageHandle);
-
- if (gLoadIsoEfi)
+ Status = ventoy_find_iso_disk(ImageHandle);
+ if (!EFI_ERROR(Status))
{
- ventoy_find_iso_disk_fs(ImageHandle);
- ventoy_load_isoefi_driver(ImageHandle);
- }
-
- ventoy_debug_pause();
-
- ventoy_install_blockio(ImageHandle, g_chain->virt_img_size_in_bytes);
+ if (gLoadIsoEfi)
+ {
+ ventoy_find_iso_disk_fs(ImageHandle);
+ ventoy_load_isoefi_driver(ImageHandle);
+ }
- ventoy_debug_pause();
+ ventoy_debug_pause();
+
+ ventoy_install_blockio(ImageHandle, g_chain->virt_img_size_in_bytes);
- Status = ventoy_boot(ImageHandle);
+ ventoy_debug_pause();
+ Status = ventoy_boot(ImageHandle);
+ }
+
ventoy_clean_env();
}
#error Unknown Processor Type
#endif
+#define VENTOY_DEVICE_WARN 0
+#define VTOY_WARNING L"!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!"
+
typedef struct ventoy_sector_flag
{
UINT8 flag; // 0:init 1:mem 2:remap
UINT32 size_be;
}ventoy_iso9660_override;
+typedef struct PART_TABLE
+{
+ UINT8 Active; // 0x00 0x80
+
+ UINT8 StartHead;
+ UINT16 StartSector : 6;
+ UINT16 StartCylinder : 10;
+
+ UINT8 FsFlag;
+
+ UINT8 EndHead;
+ UINT16 EndSector : 6;
+ UINT16 EndCylinder : 10;
+
+ UINT32 StartSectorId;
+ UINT32 SectorCount;
+}PART_TABLE;
+
+typedef struct MBR_HEAD
+{
+ UINT8 BootCode[446];
+ PART_TABLE PartTbl[4];
+ UINT8 Byte55;
+ UINT8 ByteAA;
+}MBR_HEAD;
+
#pragma pack()
common = ventoy/ventoy_linux.c;
common = ventoy/ventoy_unix.c;
common = ventoy/ventoy_windows.c;
+ common = ventoy/ventoy_vhd.c;
common = ventoy/ventoy_plugin.c;
common = ventoy/ventoy_json.c;
common = ventoy/lzx.c;
#endif
#include <grub/time.h>
#include <grub/relocator.h>
+#include <grub/charset.h>
#include <grub/ventoy.h>
#include "ventoy_def.h"
ventoy_img_chunk_list g_wimiso_chunk_list;
char *g_wimiso_path = NULL;
+int g_vhdboot_enable = 0;
+
static char *g_tree_script_buf = NULL;
static int g_tree_script_pos = 0;
static const char *g_menu_class[] =
{
- "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg"
+ "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd"
};
static const char *g_menu_prefix[] =
{
- "iso", "wim", "efi", "img"
+ "iso", "wim", "efi", "img", "vhd"
};
void ventoy_debug(const char *fmt, ...)
va_end (args);
}
+void ventoy_debug_dump_guid(const char *prefix, grub_uint8_t *guid)
+{
+ int i;
+
+ if (!g_ventoy_debug)
+ {
+ return;
+ }
+
+ debug("%s", prefix);
+ for (i = 0; i < 16; i++)
+ {
+ grub_printf("%02x ", guid[i]);
+ }
+ grub_printf("\n");
+}
+
int ventoy_is_efi_os(void)
{
if (g_efi_os > 1)
{
type = img_type_wim;
}
+ else if (g_vhdboot_enable && (0 == grub_strcasecmp(filename + len - 4, ".vhd") ||
+ 0 == grub_strcasecmp(filename + len - 5, ".vhdx")))
+ {
+ type = img_type_vhd;
+ }
#ifdef GRUB_MACHINE_EFI
else if (0 == grub_strcasecmp(filename + len - 4, ".efi"))
{
#endif
else if (0 == grub_strcasecmp(filename + len - 4, ".img"))
{
- if (len == 18 && grub_strncmp(filename, "ventoy_wimboot", 14) == 0)
+ if (len == 18 && grub_strncmp(filename, "ventoy_", 7) == 0)
{
- return 0;
+ if (grub_strncmp(filename + 7, "wimboot", 7) == 0 ||
+ grub_strncmp(filename + 7, "vhdboot", 7) == 0)
+ {
+ return 0;
+ }
}
type = img_type_img;
}
}
img->menu_prefix = g_menu_prefix[type];
+ if (img_type_iso == type)
+ {
+ if (ventoy_plugin_check_memdisk(img->path))
+ {
+ img->menu_prefix = "miso";
+ }
+ }
+
debug("Add %s%s to list %d\n", node->dir, filename, g_ventoy_img_count);
}
}
return 0;
}
+int ventoy_check_device_result(int ret)
+{
+ char buf[32];
+
+ grub_snprintf(buf, sizeof(buf), "%d", ret);
+ ventoy_set_env("VTOY_CHKDEV_RESULT_STRING", buf);
+
+ if (ret)
+ {
+ grub_printf(VTOY_WARNING"\n");
+ grub_printf(VTOY_WARNING"\n");
+ grub_printf(VTOY_WARNING"\n\n\n");
+
+ grub_printf("This is NOT a standard Ventoy device and is NOT officially supported.\n\n");
+ grub_printf("Recommend to follow the instructions in https://www.ventoy.net to use Ventoy.\n");
+
+ grub_printf("\n\nWill continue to boot after 10 seconds ...... ");
+ grub_refresh();
+ grub_sleep(10);
+ }
+
+ return ret;
+}
+
+int ventoy_check_device(grub_device_t dev)
+{
+ grub_file_t file;
+ grub_uint64_t offset;
+ char devname[64];
+ grub_fs_t fs;
+ grub_device_t dev2;
+ char *label = NULL;
+ struct grub_partition *partition;
+
+ if (dev->disk == NULL || dev->disk->partition == NULL)
+ {
+ return ventoy_check_device_result(1);
+ }
+
+ partition = dev->disk->partition;
+ if (partition->number != 0 || partition->start != 2048)
+ {
+ return ventoy_check_device_result(2);
+ }
+
+ offset = partition->start + partition->len;
+
+ /* We must have partition 2 */
+ file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "(%s,2)/ventoy/ventoy.cpio", dev->disk->name);
+ if (!file)
+ {
+ return ventoy_check_device_result(3);
+ }
+
+ partition = file->device->disk->partition;
+ if ((partition->number != 1) || (partition->len != 65536) || (offset != partition->start))
+ {
+ grub_file_close(file);
+ return ventoy_check_device_result(4);
+ }
+ grub_file_close(file);
+
+ grub_snprintf(devname, sizeof(devname), "%s,2", dev->disk->name);
+ dev2 = grub_device_open(devname);
+ if (!dev2)
+ {
+ return ventoy_check_device_result(5);
+ }
+
+ fs = grub_fs_probe(dev2);
+ if (!fs)
+ {
+ grub_device_close(dev2);
+ return ventoy_check_device_result(6);
+ }
+
+ fs->fs_label(dev2, &label);
+ if ((!label) || grub_strncmp("VTOYEFI", label, 7))
+ {
+ grub_device_close(dev2);
+ return ventoy_check_device_result(7);
+ }
+
+ grub_device_close(dev2);
+ return ventoy_check_device_result(0);
+}
+
static grub_err_t ventoy_cmd_list_img(grub_extcmd_context_t ctxt, int argc, char **args)
{
int len;
goto fail;
}
+ /* make sure that we are running in a correct Ventoy device */
+ ventoy_check_device(dev);
+
g_enum_fs = fs = grub_fs_probe(dev);
if (!fs)
{
goto fail;
}
+ ventoy_set_env("vtoy_iso_fs", fs->name);
+
strdata = ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
if (strdata && strdata[0] == '1')
{
{ "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_vhdboot", ventoy_cmd_load_vhdboot, 0, NULL, "", "", NULL },
+ { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot, 0, NULL, "", "", NULL },
{ "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64, 0, NULL, "", "", NULL },
{ "vt_load_cpio", ventoy_cmd_load_cpio, 0, NULL, "", "", NULL },
#define VTOY_SIZE_1GB 1073741824
#define VTOY_SIZE_512KB (512 * 1024)
+#define VTOY_SIZE_1KB 1024
#define JSON_SUCCESS 0
#define JSON_FAILED 1
#define ventoy_get_env(key) ventoy_env_op1(get, key)
#define ventoy_set_env(key, val) ventoy_env_op2(set, key, val)
+#define VTOY_WARNING "!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!"
+
typedef struct ventoy_initrd_ctx
{
const char *path_prefix;
#define ventoy_is_decimal(str) ventoy_string_check(str, grub_isdigit)
+#pragma pack(1)
+typedef struct ventoy_patch_vhd
+{
+ grub_uint8_t part_offset_or_guid[16];
+ grub_uint32_t reserved1;
+ grub_uint32_t part_type;
+ grub_uint8_t disk_signature_or_guid[16];
+ grub_uint8_t reserved2[16];
+ grub_uint8_t vhd_file_path[1];
+}ventoy_patch_vhd;
+#pragma pack()
+
// El Torito Boot Record Volume Descriptor
#pragma pack(1)
typedef struct eltorito_descriptor
#define img_type_wim 1
#define img_type_efi 2
#define img_type_img 3
+#define img_type_vhd 4
typedef struct img_info
{
grub_uint8_t Byte55;
grub_uint8_t ByteAA;
}ventoy_mbr_head;
+
+typedef struct ventoy_gpt_head
+{
+ char Signature[8]; /* EFI PART */
+ grub_uint8_t Version[4];
+ grub_uint32_t Length;
+ grub_uint32_t Crc;
+ grub_uint8_t Reserved1[4];
+ grub_uint64_t EfiStartLBA;
+ grub_uint64_t EfiBackupLBA;
+ grub_uint64_t PartAreaStartLBA;
+ grub_uint64_t PartAreaEndLBA;
+ grub_uint8_t DiskGuid[16];
+ grub_uint64_t PartTblStartLBA;
+ grub_uint32_t PartTblTotNum;
+ grub_uint32_t PartTblEntryLen;
+ grub_uint32_t PartTblCrc;
+ grub_uint8_t Reserved2[420];
+}ventoy_gpt_head;
+
+typedef struct ventoy_gpt_part_tbl
+{
+ grub_uint8_t PartType[16];
+ grub_uint8_t PartGuid[16];
+ grub_uint64_t StartLBA;
+ grub_uint64_t LastLBA;
+ grub_uint64_t Attr;
+ grub_uint16_t Name[36];
+}ventoy_gpt_part_tbl;
+
+typedef struct ventoy_gpt_info
+{
+ ventoy_mbr_head MBR;
+ ventoy_gpt_head Head;
+ ventoy_gpt_part_tbl PartTbl[128];
+}ventoy_gpt_info;
#pragma pack()
typedef struct file_fullpath
struct injection_config *next;
}injection_config;
+typedef struct auto_memdisk
+{
+ int pathlen;
+ char isopath[256];
+
+ struct auto_memdisk *next;
+}auto_memdisk;
+
extern int g_ventoy_menu_esc;
extern int g_ventoy_suppress_esc;
extern int g_ventoy_last_entry;
extern int g_ventoy_iso_uefi_drv;
extern int g_ventoy_case_insensitive;
extern grub_uint8_t g_ventoy_chain_type;
+extern int g_vhdboot_enable;
#define ventoy_unix_fill_virt(new_data, new_len) \
const char * ventoy_plugin_get_injection(const char *isopath);
const char * ventoy_plugin_get_menu_alias(int type, const char *isopath);
const char * ventoy_plugin_get_menu_class(int type, const char *name);
+int ventoy_plugin_check_memdisk(const char *isopath);
int ventoy_get_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist, grub_disk_addr_t start);
int ventoy_check_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist, grub_disk_addr_t start);
void ventoy_plugin_dump_persistence(void);
grub_err_t ventoy_cmd_unix_replace_ko(grub_extcmd_context_t ctxt, int argc, char **args);
grub_err_t ventoy_cmd_unix_freebsd_ver(grub_extcmd_context_t ctxt, int argc, char **args);
grub_err_t ventoy_cmd_parse_freenas_ver(grub_extcmd_context_t ctxt, int argc, char **args);
+int ventoy_check_device_result(int ret);
+int ventoy_check_device(grub_device_t dev);
+void ventoy_debug_dump_guid(const char *prefix, grub_uint8_t *guid);
+grub_err_t ventoy_cmd_load_vhdboot(grub_extcmd_context_t ctxt, int argc, char **args);
+grub_err_t ventoy_cmd_patch_vhdboot(grub_extcmd_context_t ctxt, int argc, char **args);
#endif /* __VENTOY_DEF_H__ */
static menu_alias *g_menu_alias_head = NULL;
static menu_class *g_menu_class_head = NULL;
static injection_config *g_injection_head = NULL;
+static auto_memdisk *g_auto_memdisk_head = NULL;
static int ventoy_plugin_control_check(VTOY_JSON *json, const char *isodisk)
{
return 0;
}
+static int ventoy_plugin_auto_memdisk_entry(VTOY_JSON *json, const char *isodisk)
+{
+ VTOY_JSON *pNode = NULL;
+ auto_memdisk *node = NULL;
+ auto_memdisk *next = NULL;
+
+ (void)isodisk;
+
+ if (json->enDataType != JSON_TYPE_ARRAY)
+ {
+ debug("Not array %d\n", json->enDataType);
+ return 0;
+ }
+
+ if (g_auto_memdisk_head)
+ {
+ for (node = g_auto_memdisk_head; node; node = next)
+ {
+ next = node->next;
+ grub_free(node);
+ }
+
+ g_auto_memdisk_head = NULL;
+ }
+
+ for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
+ {
+ if (pNode->enDataType == JSON_TYPE_STRING)
+ {
+ node = grub_zalloc(sizeof(auto_memdisk));
+ if (node)
+ {
+ node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", pNode->unData.pcStrVal);
+
+ if (g_auto_memdisk_head)
+ {
+ node->next = g_auto_memdisk_head;
+ }
+
+ g_auto_memdisk_head = node;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int ventoy_plugin_auto_memdisk_check(VTOY_JSON *json, const char *isodisk)
+{
+ VTOY_JSON *pNode = NULL;
+
+ if (json->enDataType != JSON_TYPE_ARRAY)
+ {
+ grub_printf("Not array %d\n", json->enDataType);
+ return 1;
+ }
+
+ for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
+ {
+ if (pNode->enDataType == JSON_TYPE_STRING)
+ {
+ grub_printf("<%s> ", pNode->unData.pcStrVal);
+
+ if (ventoy_check_file_exist("%s%s", isodisk, pNode->unData.pcStrVal))
+ {
+ grub_printf(" [OK]\n");
+ }
+ else
+ {
+ grub_printf(" [NOT EXIST]\n");
+ }
+ }
+ }
+
+ return 0;
+}
+
static plugin_entry g_plugin_entries[] =
{
{ "control", ventoy_plugin_control_entry, ventoy_plugin_control_check },
{ "menu_alias", ventoy_plugin_menualias_entry, ventoy_plugin_menualias_check },
{ "menu_class", ventoy_plugin_menuclass_entry, ventoy_plugin_menuclass_check },
{ "injection", ventoy_plugin_injection_entry, ventoy_plugin_injection_check },
+ { "auto_memdisk", ventoy_plugin_auto_memdisk_entry, ventoy_plugin_auto_memdisk_check },
};
static int ventoy_parse_plugin_config(VTOY_JSON *json, const char *isodisk)
install_template * ventoy_plugin_find_install_template(const char *isopath)
{
+ int len;
install_template *node = NULL;
- int len = (int)grub_strlen(isopath);
-
+
+ if (!g_install_template_head)
+ {
+ return NULL;
+ }
+
+ len = (int)grub_strlen(isopath);
for (node = g_install_template_head; node; node = node->next)
{
if (node->pathlen == len && grub_strcmp(node->isopath, isopath) == 0)
persistence_config * ventoy_plugin_find_persistent(const char *isopath)
{
+ int len;
persistence_config *node = NULL;
- int len = (int)grub_strlen(isopath);
-
+
+ if (!g_persistence_head)
+ {
+ return NULL;
+ }
+
+ len = (int)grub_strlen(isopath);
for (node = g_persistence_head; node; node = node->next)
{
if ((len == node->pathlen) && (grub_strcmp(node->isopath, isopath) == 0))
const char * ventoy_plugin_get_injection(const char *isopath)
{
+ int len;
injection_config *node = NULL;
- int len = (int)grub_strlen(isopath);
+ if (!g_injection_head)
+ {
+ return NULL;
+ }
+
+ len = (int)grub_strlen(isopath);
for (node = g_injection_head; node; node = node->next)
{
if (node->pathlen == len && grub_strcmp(node->isopath, isopath) == 0)
const char * ventoy_plugin_get_menu_alias(int type, const char *isopath)
{
+ int len;
menu_alias *node = NULL;
- int len = (int)grub_strlen(isopath);
+ if (!g_menu_alias_head)
+ {
+ return NULL;
+ }
+
+ len = (int)grub_strlen(isopath);
for (node = g_menu_alias_head; node; node = node->next)
{
if (node->type == type && node->pathlen &&
const char * ventoy_plugin_get_menu_class(int type, const char *name)
{
+ int len;
menu_class *node = NULL;
- int len = (int)grub_strlen(name);
+ if (!g_menu_class_head)
+ {
+ return NULL;
+ }
+
+ len = (int)grub_strlen(name);
+
if (vtoy_class_image_file == type)
{
for (node = g_menu_class_head; node; node = node->next)
return NULL;
}
+int ventoy_plugin_check_memdisk(const char *isopath)
+{
+ int len;
+ auto_memdisk *node = NULL;
+
+ if (!g_auto_memdisk_head)
+ {
+ return 0;
+ }
+
+ len = (int)grub_strlen(isopath);
+ for (node = g_auto_memdisk_head; node; node = node->next)
+ {
+ if (node->pathlen == len && grub_strncmp(isopath, node->isopath, len) == 0)
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
grub_err_t ventoy_cmd_plugin_check_json(grub_extcmd_context_t ctxt, int argc, char **args)
{
int i = 0;
--- /dev/null
+/******************************************************************************
+ * ventoy_vhd.c
+ *
+ * Copyright (c) 2020, longpanda <admin@ventoy.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/disk.h>
+#include <grub/device.h>
+#include <grub/term.h>
+#include <grub/partition.h>
+#include <grub/file.h>
+#include <grub/normal.h>
+#include <grub/extcmd.h>
+#include <grub/datetime.h>
+#include <grub/i18n.h>
+#include <grub/net.h>
+#include <grub/time.h>
+#include <grub/crypto.h>
+#include <grub/charset.h>
+#ifdef GRUB_MACHINE_EFI
+#include <grub/efi/efi.h>
+#endif
+#include <grub/ventoy.h>
+#include "ventoy_def.h"
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+static int g_vhdboot_bcd_offset = 0;
+static int g_vhdboot_bcd_len = 0;
+static int g_vhdboot_isolen = 0;
+static char *g_vhdboot_totbuf = NULL;
+static char *g_vhdboot_isobuf = NULL;
+
+static int ventoy_vhd_find_bcd(int *bcdoffset, int *bcdlen)
+{
+ grub_uint32_t offset;
+ grub_file_t file;
+ char cmdbuf[128];
+
+ grub_snprintf(cmdbuf, sizeof(cmdbuf), "loopback vhdiso mem:0x%lx:size:%d", (ulong)g_vhdboot_isobuf, g_vhdboot_isolen);
+
+ grub_script_execute_sourcecode(cmdbuf);
+
+ file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", "(vhdiso)/boot/bcd");
+ if (!file)
+ {
+ grub_printf("Failed to open bcd file in the image file\n");
+ return 1;
+ }
+
+ grub_file_read(file, &offset, 4);
+ offset = (grub_uint32_t)grub_iso9660_get_last_read_pos(file);
+
+ *bcdoffset = (int)offset;
+ *bcdlen = (int)file->size;
+
+ debug("vhdiso bcd file offset:%d len:%d\n", *bcdoffset, *bcdlen);
+
+ grub_file_close(file);
+
+ grub_script_execute_sourcecode("loopback -d vhdiso");
+
+ return 0;
+}
+
+static int ventoy_vhd_patch_path(char *vhdpath, ventoy_patch_vhd *patch1, ventoy_patch_vhd *patch2)
+{
+ int i;
+ int cnt = 0;
+ char *pos;
+ grub_size_t pathlen;
+ const char *plat;
+ grub_uint16_t *unicode_path;
+ const grub_uint8_t winloadexe[] =
+ {
+ 0x77, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x6C, 0x00, 0x6F, 0x00, 0x61, 0x00, 0x64, 0x00, 0x2E, 0x00,
+ 0x65, 0x00, 0x78, 0x00, 0x65, 0x00
+ };
+
+ pathlen = sizeof(grub_uint16_t) * (grub_strlen(vhdpath) + 1);
+ debug("unicode path for <%s> len:%d\n", vhdpath, (int)pathlen);
+
+ unicode_path = grub_zalloc(pathlen);
+ if (!unicode_path)
+ {
+ return 0;
+ }
+
+ plat = grub_env_get("grub_platform");
+
+ if (plat && (plat[0] == 'e')) /* UEFI */
+ {
+ pos = g_vhdboot_isobuf + g_vhdboot_bcd_offset;
+
+ /* winload.exe ==> winload.efi */
+ for (i = 0; i + (int)sizeof(winloadexe) < g_vhdboot_bcd_len; i++)
+ {
+ if (*((grub_uint32_t *)(pos + i)) == 0x00690077 &&
+ grub_memcmp(pos + i, winloadexe, sizeof(winloadexe)) == 0)
+ {
+ pos[i + sizeof(winloadexe) - 4] = 0x66;
+ pos[i + sizeof(winloadexe) - 2] = 0x69;
+ cnt++;
+ }
+ }
+
+ debug("winload patch %d times\n", cnt);
+ }
+
+ for (pos = vhdpath; *pos; pos++)
+ {
+ if (*pos == '/')
+ {
+ *pos = '\\';
+ }
+ }
+
+ grub_utf8_to_utf16(unicode_path, pathlen, (grub_uint8_t *)vhdpath, -1, NULL);
+ grub_memcpy(patch1->vhd_file_path, unicode_path, pathlen);
+ grub_memcpy(patch2->vhd_file_path, unicode_path, pathlen);
+
+ return 0;
+}
+
+static int ventoy_vhd_patch_disk(char *isopart, ventoy_patch_vhd *patch1, ventoy_patch_vhd *patch2)
+{
+ char *pos;
+ grub_disk_t disk;
+ ventoy_gpt_info *gptinfo;
+ char efipart[16] = {0};
+
+ pos = grub_strchr(isopart, ',');
+ if (pos)
+ {
+ *pos = 0;
+ }
+
+ pos = isopart;
+ if (*pos == '(')
+ {
+ pos++;
+ }
+
+ debug("vhd disk <%s>\n", pos);
+
+ disk = grub_disk_open(pos);
+ if (!disk)
+ {
+ debug("Failed to open disk %s\n", pos);
+ return 1;
+ }
+
+ gptinfo = (ventoy_gpt_info *)(g_vhdboot_isobuf + g_vhdboot_isolen);
+ grub_disk_read(disk, 0, 0, sizeof(ventoy_gpt_info), gptinfo);
+
+ grub_memcpy(efipart, gptinfo->Head.Signature, sizeof(gptinfo->Head.Signature));
+
+ debug("part1 type: 0x%x <%s>\n", gptinfo->MBR.PartTbl[0].FsFlag, efipart);
+
+ if (grub_strncmp(efipart, "EFI PART", 8) == 0)
+ {
+ ventoy_debug_dump_guid("GPT disk GUID: ", gptinfo->Head.DiskGuid);
+ ventoy_debug_dump_guid("GPT part GUID: ", gptinfo->PartTbl[0].PartGuid);
+
+ grub_memcpy(patch1->disk_signature_or_guid, gptinfo->Head.DiskGuid, 16);
+ grub_memcpy(patch1->part_offset_or_guid, gptinfo->PartTbl[0].PartGuid, 16);
+ grub_memcpy(patch2->disk_signature_or_guid, gptinfo->Head.DiskGuid, 16);
+ grub_memcpy(patch2->part_offset_or_guid, gptinfo->PartTbl[0].PartGuid, 16);
+
+ patch1->part_type = patch2->part_type = 0;
+ }
+ else
+ {
+ debug("MBR disk signature: %02x%02x%02x%02x\n",
+ gptinfo->MBR.BootCode[0x1b8 + 0], gptinfo->MBR.BootCode[0x1b8 + 1],
+ gptinfo->MBR.BootCode[0x1b8 + 2], gptinfo->MBR.BootCode[0x1b8 + 3]);
+ grub_memcpy(patch1->disk_signature_or_guid, gptinfo->MBR.BootCode + 0x1b8, 4);
+ grub_memcpy(patch2->disk_signature_or_guid, gptinfo->MBR.BootCode + 0x1b8, 4);
+ }
+
+ grub_disk_close(disk);
+
+ return 0;
+}
+
+grub_err_t ventoy_cmd_patch_vhdboot(grub_extcmd_context_t ctxt, int argc, char **args)
+{
+ int rc;
+ ventoy_patch_vhd *patch1;
+ ventoy_patch_vhd *patch2;
+ char envbuf[64];
+
+ (void)ctxt;
+ (void)argc;
+
+ grub_env_unset("vtoy_vhd_buf_addr");
+
+ debug("patch vhd <%s> <%s>\n", args[0], args[1]);
+
+ if ((!g_vhdboot_enable) || (!g_vhdboot_totbuf))
+ {
+ debug("vhd boot not ready %d %p\n", g_vhdboot_enable, g_vhdboot_totbuf);
+ return 0;
+ }
+
+ rc = ventoy_vhd_find_bcd(&g_vhdboot_bcd_offset, &g_vhdboot_bcd_len);
+ if (rc)
+ {
+ debug("failed to get bcd location %d\n", rc);
+ return 0;
+ }
+
+ patch1 = (ventoy_patch_vhd *)(g_vhdboot_isobuf + g_vhdboot_bcd_offset + 0x495a);
+ patch2 = (ventoy_patch_vhd *)(g_vhdboot_isobuf + g_vhdboot_bcd_offset + 0x50aa);
+
+ ventoy_vhd_patch_disk(args[0], patch1, patch2);
+ ventoy_vhd_patch_path(args[1], patch1, patch2);
+
+ /* set buffer and size */
+#ifdef GRUB_MACHINE_EFI
+ grub_snprintf(envbuf, sizeof(envbuf), "0x%lx", (ulong)g_vhdboot_totbuf);
+ grub_env_set("vtoy_vhd_buf_addr", envbuf);
+ grub_snprintf(envbuf, sizeof(envbuf), "%d", (int)(g_vhdboot_isolen + sizeof(ventoy_chain_head)));
+ grub_env_set("vtoy_vhd_buf_size", envbuf);
+#else
+ grub_snprintf(envbuf, sizeof(envbuf), "0x%lx", (ulong)g_vhdboot_isobuf);
+ grub_env_set("vtoy_vhd_buf_addr", envbuf);
+ grub_snprintf(envbuf, sizeof(envbuf), "%d", g_vhdboot_isolen);
+ grub_env_set("vtoy_vhd_buf_size", envbuf);
+#endif
+
+ return 0;
+}
+
+grub_err_t ventoy_cmd_load_vhdboot(grub_extcmd_context_t ctxt, int argc, char **args)
+{
+ int buflen;
+ grub_file_t file;
+
+ (void)ctxt;
+ (void)argc;
+
+ g_vhdboot_enable = 0;
+ grub_check_free(g_vhdboot_totbuf);
+
+ file = grub_file_open(args[0], VENTOY_FILE_TYPE);
+ if (!file)
+ {
+ return 0;
+ }
+
+ debug("load vhd boot: <%s> <%lu>\n", args[0], (ulong)file->size);
+
+ if (file->size < VTOY_SIZE_1KB * 32)
+ {
+ grub_file_close(file);
+ return 0;
+ }
+
+ g_vhdboot_isolen = (int)file->size;
+
+ buflen = (int)(file->size + sizeof(ventoy_gpt_info) + sizeof(ventoy_chain_head));
+
+#ifdef GRUB_MACHINE_EFI
+ g_vhdboot_totbuf = (char *)grub_efi_allocate_iso_buf(buflen);
+#else
+ g_vhdboot_totbuf = (char *)grub_malloc(buflen);
+#endif
+
+ if (!g_vhdboot_totbuf)
+ {
+ grub_file_close(file);
+ return 0;
+ }
+
+ g_vhdboot_isobuf = g_vhdboot_totbuf + sizeof(ventoy_chain_head);
+
+ grub_file_read(file, g_vhdboot_isobuf, file->size);
+ grub_file_close(file);
+
+ g_vhdboot_enable = 1;
+
+ return 0;
+}
+
if [ "$1" = "uefi" ]; then
all_modules="$net_modules_uefi $all_modules_uefi "
grub-mkimage -v --directory "$VT_DIR/GRUB2/INSTALL/lib/grub/x86_64-efi" --prefix '(,2)/grub' --output "$VT_DIR/INSTALL/EFI/BOOT/grubx64_real.efi" --format 'x86_64-efi' --compression 'auto' $all_modules_uefi 'fat' 'part_msdos'
+
+ #grub-mkimage -v --directory "$VT_DIR/GRUB2/INSTALL/lib/grub/x86_64-efi" -c "$VT_DIR/LiveCD/GRUB/embed.cfg" --prefix '/EFI/boot' --output "$VT_DIR/LiveCD/GRUB/bootx64.efi" --format 'x86_64-efi' --compression 'auto' $all_modules_uefi 'fat' 'part_msdos'
else
all_modules="$net_modules_legacy $all_modules_legacy "
grub-mkimage -v --directory "$VT_DIR/GRUB2/INSTALL/lib/grub/i386-pc" --prefix '(,2)/grub' --output "$VT_DIR/INSTALL/grub/i386-pc/core.img" --format 'i386-pc' --compression 'auto' $all_modules_legacy 'fat' 'part_msdos' 'biosdisk'
+
+ #grub-mkimage -v --directory "$VT_DIR/GRUB2/INSTALL/lib/grub/i386-pc" -c "$VT_DIR/LiveCD/GRUB/embed.cfg" --prefix '/EFI/boot' --output "$VT_DIR/LiveCD/GRUB/cdrom.img" --format 'i386-pc-eltorito' --compression 'auto' $all_modules_legacy 'biosdisk' 'iso9660' 'fat' 'part_msdos'
+ #rm -f $VT_DIR/LiveCD/GRUB/boot_hybrid.img
+ #cp -a $VT_DIR/GRUB2/INSTALL/lib/grub/i386-pc/boot_hybrid.img $VT_DIR/LiveCD/GRUB/boot_hybrid.img
fi
grub-mknetdir --modules="$all_modules" --net-directory=$VT_DIR/GRUB2/PXE --subdir=grub2 --locales=en@quot || exit 1
echo "##### distribution = $DISTRO ######" >> $VTLOG
. $VTOY_PATH/hook/debian/${DISTRO}-hook.sh
-
-
-
-
+if [ -f /bin/env2debconf ]; then
+ $SED "1a /bin/sh $VTOY_PATH/hook/debian/ventoy_env2debconf.sh" -i /bin/env2debconf
+ $SED "s#in *\$(set)#in \$(cat /ventoy/envset)#" -i /bin/env2debconf
+fi
--- /dev/null
+#!/bin/sh
+#************************************************************************************
+# Copyright (c) 2020, longpanda <admin@ventoy.net>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+#
+#************************************************************************************
+
+PATH=$PATH:/ventoy/busybox
+
+set > /ventoy/tmpenvset
+
+for i in $(cat /proc/cmdline); do
+ if echo $i | grep -q "="; then
+ vtKey=${i%=*}
+ if ! grep -q "^$vtKey" /ventoy/tmpenvset; then
+ echo $i >> /ventoy/envset
+ fi
+ fi
+done
+
+cat /ventoy/tmpenvset >> /ventoy/envset
cd /
-unset VTLOG FIND GREP EGREP CAT AWK SED SLEEP HEAD
+unset VTLOG FIND GREP EGREP CAT AWK SED SLEEP HEAD vtcmdline
for vtinit in $user_rdinit /init /sbin/init /linuxrc; do
if [ -d /ventoy_rdroot ]; then
elif [ -f (loop)/hyperbola/boot/x86_64/hyperiso.img ]; then
vt_add_replace_file 0 "EFI\\hyperiso\\hyperiso.img"
fi
+ elif [ -d (loop)/EFI/BOOT/entries ]; then
+ if [ -f (loop)/parabola/boot/x86_64/parabolaiso.img ]; then
+ vt_add_replace_file 0 "EFI\\parabolaiso\\parabolaiso.img"
+ fi
elif [ -e (loop)/syslinux/alt0/full.cz ]; then
vt_add_replace_file 0 "EFI\\BOOT\\full.cz"
set FirstTryBootFile='@EFI@BOOT@grubx64.efi'
if [ -n "$vtoy_chain_mem_addr" ]; then
linux16 $vtoy_path/ipxe.krn ${vtdebug_flag} ibft mem:${vtoy_chain_mem_addr}:size:${vtoy_chain_mem_size}
+ set gfxmode=1920x1080,1366x768,1024x768,800x600,auto
+ terminal_output gfxterm
boot
else
echo "chain empty failed"
fi
}
+function miso_common_menuentry {
+ vt_chosen_img_path vt_chosen_path vt_chosen_size
+
+ if [ "$grub_platform" = "pc" ]; then
+ legacy_iso_memdisk $vtoy_iso_part $vt_chosen_path
+ else
+ uefi_iso_memdisk $vtoy_iso_part $vt_chosen_path
+ fi
+}
+
+
function common_unsupport_menuentry {
echo -e "\n The name of the iso file could NOT contain space or non-ascii characters. \n"
echo -e " 文件名中不能有中文或空格 \n"
read vtInputKey
}
+function miso_unsupport_menuentry {
+ common_unsupport_menuentry
+}
+
function iso_unsupport_menuentry {
common_unsupport_menuentry
}
if [ -n "$vtoy_chain_mem_addr" ]; then
if [ "$grub_platform" = "pc" ]; then
linux16 $vtoy_path/ipxe.krn ${vtdebug_flag} mem:${vtoy_chain_mem_addr}:size:${vtoy_chain_mem_size}
+ set gfxmode=1920x1080,1366x768,1024x768,800x600,auto
+ terminal_output gfxterm
else
ventoy_cli_console
chainloader ${vtoy_path}/ventoy_x64.efi env_param=${env_param} isoefi=${LoadIsoEfiDriver} ${vtdebug_flag} mem:${vtoy_chain_mem_addr}:size:${vtoy_chain_mem_size}
common_unsupport_menuentry
}
+
+function vhd_common_menuentry {
+
+ if [ "$VTOY_VHD_NO_WARNING" != "1" ]; then
+ if [ "$vtoy_iso_fs" != "ntfs" ]; then
+ echo -e "!!! WARNING !!!\n"
+ echo -e "\nPartition1 ($vtoy_iso_fs) is NOT ntfs, the VHD(x) file may not boot normally \n"
+ echo -e "\nVHD(x) 文件所在分区不是 ntfs 格式, 可能无法正常启动 \n\n"
+ echo -n "press ENTER to continue boot (请按 回车 键继续) ..."
+ read vtInputKey
+ fi
+ fi
+
+ vt_chosen_img_path vt_chosen_path vt_chosen_size
+ vt_patch_vhdboot ${vtoy_iso_part} ${vt_chosen_path}
+
+ ventoy_debug_pause
+
+ if [ -n "$vtoy_vhd_buf_addr" ]; then
+ if [ "$grub_platform" = "pc" ]; then
+ linux16 $vtoy_path/memdisk iso raw
+ initrd16 mem:${vtoy_vhd_buf_addr}:size:${vtoy_vhd_buf_size}
+
+ set gfxmode=1920x1080,1366x768,1024x768,800x600,auto
+ terminal_output gfxterm
+ boot
+ else
+ ventoy_cli_console
+ chainloader ${vtoy_path}/ventoy_x64.efi memdisk env_param=${env_param} isoefi=${LoadIsoEfiDriver} ${vtdebug_flag} mem:${vtoy_vhd_buf_addr}:size:${vtoy_vhd_buf_size}
+ boot
+ ventoy_gui_console
+ fi
+ else
+ echo "Failed to boot vhd file"
+ ventoy_pause
+ fi
+}
+
+function vhd_unsupport_menuentry {
+ common_unsupport_menuentry
+}
+
#
#============================================================#
# IMG file boot process #
vt_load_wimboot $vtoy_efi_part/ventoy/ventoy_wimboot.img
fi
+if [ -f $vtoy_iso_part/ventoy/ventoy_vhdboot.img ]; then
+ vt_load_vhdboot $vtoy_iso_part/ventoy/ventoy_vhdboot.img
+elif [ -f $vtoy_efi_part/ventoy/ventoy_vhdboot.img ]; then
+ vt_load_vhdboot $vtoy_efi_part/ventoy/ventoy_vhdboot.img
+fi
+
if [ $VTOY_DEFAULT_MENU_MODE -eq 0 ]; then
set VTOY_F3_CMD="vt_dynamic_menu 1 1"
if [ -n "$vtoy_gfxmode" ]; then
set gfxmode=$vtoy_gfxmode
else
- set gfxmode=1920x1080,1366x768,1024x768
+ set gfxmode=1920x1080,1366x768,1024x768,800x600,auto
fi
if [ "$vtoy_display_mode" = "CLI" ]; then
if (MBR.PartTbl[0].Active != 0x80 && MBR.PartTbl[1].Active != 0x80)\r
{\r
Log("Part1 and Part2 are both NOT active 0x%x 0x%x", MBR.PartTbl[0].Active, MBR.PartTbl[1].Active);\r
- return FALSE;\r
+ if (MBR.PartTbl[2].Active != 0x80 && MBR.PartTbl[3].Active != 0x80)\r
+ {\r
+ Log("Part3 and Part4 are both NOT active 0x%x 0x%x", MBR.PartTbl[2].Active, MBR.PartTbl[3].Active);\r
+ return FALSE;\r
+ }\r
}\r
\r
*Part2StartSector = MBR.PartTbl[1].StartSectorId;\r