mirror of https://github.com/ventoy/Ventoy.git
1.0.64 release
This commit is contained in:
parent
25dc323522
commit
1f49265f29
|
@ -1,9 +1,11 @@
|
|||
#!/bin/sh
|
||||
|
||||
DSTDIR=../../IMG/cpio/ventoy/busybox
|
||||
DSTDIR1=../../IMG/cpio_x86/ventoy/busybox
|
||||
DSTDIR2=../../IMG/cpio_arm64/ventoy/busybox
|
||||
DSTDIR3=../../IMG/cpio_mips64/ventoy/busybox
|
||||
|
||||
rm -f vtchmod32 vtchmod64 vtchmod64_musl vtchmodaa64
|
||||
rm -f $DSTDIR/vtchmod32 $DSTDIR/vtchmod64 $DSTDIR/vtchmodaa64 $DSTDIR/vtchmodm64e
|
||||
rm -f $DSTDIR1/vtchmod32 $DSTDIR1/vtchmod64 $DSTDIR2/vtchmodaa64 $DSTDIR3/vtchmodm64e
|
||||
|
||||
/opt/diet32/bin/diet gcc -Os -m32 vtchmod.c -o vtchmod32
|
||||
/opt/diet64/bin/diet gcc -Os vtchmod.c -o vtchmod64
|
||||
|
@ -23,9 +25,9 @@ chmod 777 vtchmodaa64
|
|||
chmod 777 vtchmod64_musl
|
||||
chmod 777 vtchmodm64e
|
||||
|
||||
cp -a vtchmod32 $DSTDIR/
|
||||
cp -a vtchmod64 $DSTDIR/
|
||||
cp -a vtchmodaa64 $DSTDIR/
|
||||
cp -a vtchmod64_musl $DSTDIR/
|
||||
cp -a vtchmodm64e $DSTDIR/
|
||||
cp -a vtchmod32 $DSTDIR1/
|
||||
cp -a vtchmod64 $DSTDIR1/
|
||||
cp -a vtchmod64_musl $DSTDIR1/
|
||||
cp -a vtchmodaa64 $DSTDIR2/
|
||||
cp -a vtchmodm64e $DSTDIR3/
|
||||
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
@ -8,6 +11,24 @@ int main(int argc, char **argv)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (argv[1][0] == '-' && argv[1][1] == '6')
|
||||
{
|
||||
struct utsname buf;
|
||||
if (0 == uname(&buf))
|
||||
{
|
||||
if (strstr(buf.machine, "amd64"))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strstr(buf.machine, "x86_64"))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
return chmod(argv[1], 0777);
|
||||
}
|
||||
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,7 @@
|
|||
|
||||
obj-m += dm_patch.o
|
||||
|
||||
EXTRA_CFLAGS := -Wall
|
||||
|
||||
dm_patch-objs := dmpatch.o
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
/******************************************************************************
|
||||
* dmpatch.c ---- patch for device-mapper
|
||||
*
|
||||
* Copyright (c) 2021, 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 <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kallsyms.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/mempool.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define MAX_PATCH 4
|
||||
|
||||
#define magic_sig 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF
|
||||
|
||||
typedef int (*kprobe_reg_pf)(void *);
|
||||
typedef void (*kprobe_unreg_pf)(void *);
|
||||
typedef int (*printk_pf)(const char *fmt, ...);
|
||||
typedef int (*set_memory_attr_pf)(unsigned long addr, int numpages);
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct ko_param
|
||||
{
|
||||
unsigned char magic[16];
|
||||
unsigned long struct_size;
|
||||
unsigned long pgsize;
|
||||
unsigned long printk_addr;
|
||||
unsigned long ro_addr;
|
||||
unsigned long rw_addr;
|
||||
unsigned long reg_kprobe_addr;
|
||||
unsigned long unreg_kprobe_addr;
|
||||
unsigned long sym_get_addr;
|
||||
unsigned long sym_get_size;
|
||||
unsigned long sym_put_addr;
|
||||
unsigned long sym_put_size;
|
||||
unsigned long padding[3];
|
||||
}ko_param;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
static printk_pf kprintf = NULL;
|
||||
static set_memory_attr_pf set_mem_ro = NULL;
|
||||
static set_memory_attr_pf set_mem_rw = NULL;
|
||||
static kprobe_reg_pf reg_kprobe = NULL;
|
||||
static kprobe_unreg_pf unreg_kprobe = NULL;
|
||||
|
||||
static volatile ko_param g_ko_param =
|
||||
{
|
||||
{ magic_sig },
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
|
||||
#define CODE_MATCH(code, i) \
|
||||
(code[i] == 0x40 && code[i + 1] == 0x80 && code[i + 2] == 0xce && code[i + 3] == 0x80)
|
||||
|
||||
#define vdebug(fmt, args...) if(kprintf) kprintf(KERN_ERR fmt, ##args)
|
||||
|
||||
static int notrace dmpatch_replace_code(unsigned long addr, unsigned long size, int expect, const char *desc)
|
||||
{
|
||||
int i = 0;
|
||||
int cnt = 0;
|
||||
unsigned long align;
|
||||
unsigned char *patch[MAX_PATCH];
|
||||
unsigned char *opCode = (unsigned char *)addr;
|
||||
|
||||
vdebug("patch for %s 0x%lx %d\n", desc, addr, (int)size);
|
||||
|
||||
for (i = 0; i < (int)size - 4; i++)
|
||||
{
|
||||
if (CODE_MATCH(opCode, i) && cnt < MAX_PATCH)
|
||||
{
|
||||
patch[cnt] = opCode + i + 3;
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
if (cnt != expect || cnt >= MAX_PATCH)
|
||||
{
|
||||
vdebug("patch error: cnt=%d expect=%d\n", cnt, expect);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < cnt; i++)
|
||||
{
|
||||
opCode = patch[i];
|
||||
align = (unsigned long)opCode / g_ko_param.pgsize * g_ko_param.pgsize;
|
||||
|
||||
set_mem_rw(align, 1);
|
||||
*opCode = 0;
|
||||
set_mem_ro(align, 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int notrace dmpatch_init(void)
|
||||
{
|
||||
int r = 0;
|
||||
int rc = 0;
|
||||
|
||||
kprintf = (printk_pf)(g_ko_param.printk_addr);
|
||||
|
||||
vdebug("dmpatch_init start pagesize=%lu ...\n", g_ko_param.pgsize);
|
||||
|
||||
if (g_ko_param.struct_size != sizeof(ko_param))
|
||||
{
|
||||
vdebug("Invalid struct size %d %d\n", (int)g_ko_param.struct_size, (int)sizeof(ko_param));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (g_ko_param.sym_get_addr == 0 || g_ko_param.sym_put_addr == 0 ||
|
||||
g_ko_param.ro_addr == 0 || g_ko_param.rw_addr == 0)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
set_mem_ro = (set_memory_attr_pf)(g_ko_param.ro_addr);
|
||||
set_mem_rw = (set_memory_attr_pf)(g_ko_param.rw_addr);
|
||||
reg_kprobe = (kprobe_reg_pf)g_ko_param.reg_kprobe_addr;
|
||||
unreg_kprobe = (kprobe_unreg_pf)g_ko_param.unreg_kprobe_addr;
|
||||
|
||||
r = dmpatch_replace_code(g_ko_param.sym_get_addr, g_ko_param.sym_get_size, 2, "dm_get_table_device");
|
||||
if (r)
|
||||
{
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
vdebug("patch dm_get_table_device success\n");
|
||||
|
||||
r = dmpatch_replace_code(g_ko_param.sym_put_addr, g_ko_param.sym_put_size, 1, "dm_put_table_device");
|
||||
if (r)
|
||||
{
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
vdebug("patch dm_put_table_device success\n");
|
||||
|
||||
vdebug("#####################################\n");
|
||||
vdebug("######## dm patch success ###########\n");
|
||||
vdebug("#####################################\n");
|
||||
|
||||
out:
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void notrace dmpatch_exit(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
module_init(dmpatch_init);
|
||||
module_exit(dmpatch_exit);
|
||||
|
||||
|
||||
MODULE_DESCRIPTION("dmpatch driver");
|
||||
MODULE_AUTHOR("longpanda <admin@ventoy.net>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
1. install ubuntu 21.10
|
||||
2. apt-get install build-essential flex ncurse linux-headers-generic linux-source ...... and so on
|
||||
3. cp /lib/modules/5.13.0-23-generic/build/Module.symvers ./
|
||||
4. /boot/config-5.13.0-23-generic as .config make oldconfig
|
||||
5. make menuconfig
|
||||
1. close CONFIG_STACKPROTECTOR
|
||||
2. close CONFIG_RETPOLINE
|
||||
|
||||
6. modify ./scripts/mod/modpost.c
|
||||
1. skip add_srcversion (just return)
|
||||
2. force add_retpoline (#ifdef --> #ifndef)
|
||||
|
||||
7. make modules_prepare LOCALVERSION=-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
|
||||
8. Append padding at the end of struct module <include/linux/module.h>
|
||||
struct module {
|
||||
enum module_state state;
|
||||
|
||||
/* Member of list of modules */
|
||||
struct list_head list;
|
||||
|
||||
/* Unique handle for this module */
|
||||
char name[MODULE_NAME_LEN];
|
||||
|
||||
....
|
||||
|
||||
char padding[1024];
|
||||
};
|
||||
|
||||
This is because struct module size is different in different kernel versions or with different CONFIG item.
|
||||
|
||||
|
||||
9. make modules M=/home/dmpatch
|
||||
10. strip --strip-debug /home/dmpatch/dm_patch.ko
|
||||
|
|
@ -249,6 +249,12 @@ EFI_STATUS EFIAPI vdisk_exit_boot_service_wrapper
|
|||
IN UINTN MapKey
|
||||
)
|
||||
{
|
||||
if (g_org_get_variable)
|
||||
{
|
||||
gRT->GetVariable = g_org_get_variable;
|
||||
g_org_get_variable = NULL;
|
||||
}
|
||||
|
||||
return g_org_exit_boot_service(ImageHandle, MapKey);
|
||||
}
|
||||
|
||||
|
|
|
@ -71,6 +71,9 @@ STATIC BOOLEAN g_hook_keyboard = FALSE;
|
|||
|
||||
CHAR16 gFirstTryBootFile[256] = {0};
|
||||
|
||||
STATIC EFI_GET_VARIABLE g_org_get_variable = NULL;
|
||||
STATIC EFI_EXIT_BOOT_SERVICES g_org_exit_boot_service = NULL;
|
||||
|
||||
/* Boot filename */
|
||||
UINTN gBootFileStartIndex = 1;
|
||||
CONST CHAR16 *gEfiBootFileName[] =
|
||||
|
@ -739,6 +742,77 @@ STATIC EFI_STATUS ventoy_proc_img_replace_name(ventoy_grub_param_file_replace *r
|
|||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_get_variable_wrapper
|
||||
(
|
||||
IN CHAR16 *VariableName,
|
||||
IN EFI_GUID *VendorGuid,
|
||||
OUT UINT32 *Attributes, OPTIONAL
|
||||
IN OUT UINTN *DataSize,
|
||||
OUT VOID *Data OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
|
||||
Status = g_org_get_variable(VariableName, VendorGuid, Attributes, DataSize, Data);
|
||||
if (StrCmp(VariableName, L"SecureBoot") == 0)
|
||||
{
|
||||
if ((*DataSize == 1) && Data)
|
||||
{
|
||||
*(UINT8 *)Data = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_exit_boot_service_wrapper
|
||||
(
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN UINTN MapKey
|
||||
)
|
||||
{
|
||||
if (g_org_get_variable)
|
||||
{
|
||||
gRT->GetVariable = g_org_get_variable;
|
||||
g_org_get_variable = NULL;
|
||||
}
|
||||
|
||||
return g_org_exit_boot_service(ImageHandle, MapKey);
|
||||
}
|
||||
|
||||
STATIC EFI_STATUS EFIAPI ventoy_disable_secure_boot(IN EFI_HANDLE ImageHandle)
|
||||
{
|
||||
UINT8 Value = 0;
|
||||
UINTN DataSize = 1;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
|
||||
Status = gRT->GetVariable(L"SecureBoot", &gEfiGlobalVariableGuid, NULL, &DataSize, &Value);
|
||||
if (!EFI_ERROR(Status))
|
||||
{
|
||||
if (DataSize == 1 && Value == 0)
|
||||
{
|
||||
debug("Current secure boot is off, no need to disable");
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
debug("ventoy_disable_secure_boot");
|
||||
|
||||
/* step1: wrapper security protocol. */
|
||||
/* Do we still need it since we have been loaded ? */
|
||||
|
||||
|
||||
/* step2: fake SecureBoot variable */
|
||||
g_org_exit_boot_service = gBS->ExitBootServices;
|
||||
gBS->ExitBootServices = ventoy_exit_boot_service_wrapper;
|
||||
|
||||
g_org_get_variable = gRT->GetVariable;
|
||||
gRT->GetVariable = ventoy_get_variable_wrapper;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
|
||||
{
|
||||
UINT32 i = 0;
|
||||
|
@ -910,6 +984,11 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
|
|||
g_hook_keyboard = TRUE;
|
||||
}
|
||||
|
||||
if (g_os_param_reserved[5] == 1 && g_os_param_reserved[2] == ventoy_chain_linux)
|
||||
{
|
||||
ventoy_disable_secure_boot(ImageHandle);
|
||||
}
|
||||
|
||||
debug("internal param: secover:%u keyboard:%u", g_fixup_iso9660_secover_enable, g_hook_keyboard);
|
||||
|
||||
for (i = 0; i < sizeof(ventoy_os_param); i++)
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
DebugLib
|
||||
|
||||
[Guids]
|
||||
gEfiGlobalVariableGuid
|
||||
gShellVariableGuid
|
||||
gEfiVirtualCdGuid
|
||||
gEfiFileInfoGuid
|
||||
|
|
|
@ -2748,6 +2748,7 @@ void ventoy_fill_os_param(grub_file_t file, ventoy_os_param *param)
|
|||
{
|
||||
char *pos;
|
||||
const char *fs = NULL;
|
||||
const char *val = NULL;
|
||||
const char *cdprompt = NULL;
|
||||
grub_uint32_t i;
|
||||
grub_uint8_t chksum = 0;
|
||||
|
@ -2794,6 +2795,13 @@ void ventoy_fill_os_param(grub_file_t file, ventoy_os_param *param)
|
|||
param->vtoy_reserved[3] = 1;
|
||||
}
|
||||
|
||||
param->vtoy_reserved[5] = 0;
|
||||
val = ventoy_get_env("VTOY_LINUX_REMOUNT");
|
||||
if (val && val[0] == '1' && val[1] == 0)
|
||||
{
|
||||
param->vtoy_reserved[5] = 1;
|
||||
}
|
||||
|
||||
/* calculate checksum */
|
||||
for (i = 0; i < sizeof(ventoy_os_param); i++)
|
||||
{
|
||||
|
|
|
@ -121,6 +121,7 @@ typedef struct ventoy_os_param
|
|||
* vtoy_reserved[2]: vtoy_chain_type 0:Linux 1:Windows 2:wimfile
|
||||
* vtoy_reserved[3]: vtoy_iso_format 0:iso9660 1:udf
|
||||
* vtoy_reserved[4]: vtoy_windows_cd_prompt
|
||||
* vtoy_reserved[5]: vtoy_linux_remount
|
||||
*
|
||||
*/
|
||||
grub_uint8_t vtoy_reserved[32]; // Internal use by ventoy
|
||||
|
|
|
@ -48,6 +48,12 @@ else
|
|||
fi
|
||||
fi
|
||||
|
||||
if [ "$VTOY_ARCH" = "i386" ]; then
|
||||
if $BUSYBOX_PATH/vtchmod32 -6; then
|
||||
export VTOY_ARCH=x86_64
|
||||
fi
|
||||
fi
|
||||
|
||||
echo $VTOY_ARCH > $VTOY_PATH/ventoy_arch
|
||||
|
||||
|
||||
|
@ -81,6 +87,7 @@ export PATH=$BUSYBOX_PATH/:$VTOY_PATH/tool
|
|||
|
||||
export VTOY_BREAK_LEVEL=$(hexdump -n 1 -s 449 -e '1/1 "%02x"' $VTOY_PATH/ventoy_os_param)
|
||||
export VTOY_DEBUG_LEVEL=$(hexdump -n 1 -s 450 -e '1/1 "%02x"' $VTOY_PATH/ventoy_os_param)
|
||||
export VTOY_LINUX_REMOUNT=$(hexdump -n 1 -s 454 -e '1/1 "%02x"' $VTOY_PATH/ventoy_os_param)
|
||||
|
||||
#Fixme: busybox shell output redirect seems to have some bug in rhel5
|
||||
if uname -a | grep -q el5; then
|
||||
|
|
|
@ -30,6 +30,7 @@ SLEEP=$BUSYBOX_PATH/sleep
|
|||
HEAD=$BUSYBOX_PATH/head
|
||||
VTOY_DM_PATH=/dev/mapper/ventoy
|
||||
VTOY_DEBUG_LEVEL=$($BUSYBOX_PATH/hexdump -n 1 -s 450 -e '1/1 "%02x"' $VTOY_PATH/ventoy_os_param)
|
||||
VTOY_LINUX_REMOUNT=$($BUSYBOX_PATH/hexdump -n 1 -s 454 -e '1/1 "%02x"' $VTOY_PATH/ventoy_os_param)
|
||||
|
||||
if [ "$VTOY_DEBUG_LEVEL" = "01" ]; then
|
||||
if [ -e /dev/console ]; then
|
||||
|
@ -220,6 +221,125 @@ ventoy_check_dm_module() {
|
|||
fi
|
||||
}
|
||||
|
||||
ventoy_need_dm_patch() {
|
||||
if [ "$VTOY_LINUX_REMOUNT" != "01" ]; then
|
||||
$BUSYBOX_PATH/false; return
|
||||
fi
|
||||
|
||||
if $GREP -q 'device-mapper' /proc/devices; then
|
||||
:
|
||||
else
|
||||
$BUSYBOX_PATH/false; return
|
||||
fi
|
||||
|
||||
if $GREP -q 'dm_patch' /proc/modules; then
|
||||
$BUSYBOX_PATH/false; return
|
||||
fi
|
||||
|
||||
vtMajorVer=$($BUSYBOX_PATH/uname -r | $AWK -F. '{print $1}')
|
||||
vtMinorVer=$($BUSYBOX_PATH/uname -r | $AWK -F. '{print $2}')
|
||||
|
||||
if [ $vtMajorVer -lt 3 ]; then
|
||||
$BUSYBOX_PATH/false; return
|
||||
elif [ $vtMajorVer -eq 3 -a $vtMinorVer -lt 10 ]; then
|
||||
$BUSYBOX_PATH/false; return
|
||||
fi
|
||||
|
||||
|
||||
$BUSYBOX_PATH/true
|
||||
}
|
||||
|
||||
ventoy_dm_patch() {
|
||||
vtMType=$($BUSYBOX_PATH/uname -m)
|
||||
|
||||
vtlog "######### ventoy_dm_patch ############"
|
||||
|
||||
if echo $vtMType | $EGREP -i -q "x86.64|amd64"; then
|
||||
vtKoName=dm_patch_64.ko
|
||||
else
|
||||
vtlog "unsupported machine type $vtMType"
|
||||
return
|
||||
fi
|
||||
|
||||
if [ -f $VTOY_PATH/tool/$vtKoName ]; then
|
||||
vtlog "/ventoy/tool/$vtKoName exist OK"
|
||||
else
|
||||
vtlog "/ventoy/tool/$vtKoName NOT exist"
|
||||
return
|
||||
fi
|
||||
|
||||
$CAT /proc/kallsyms | $BUSYBOX_PATH/sort > $VTOY_PATH/kallsyms
|
||||
|
||||
vtLine=$($VTOY_PATH/tool/vtoyksym dm_get_table_device $VTOY_PATH/kallsyms)
|
||||
get_addr=$(echo $vtLine | $AWK '{print $1}')
|
||||
get_size=$(echo $vtLine | $AWK '{print $2}')
|
||||
|
||||
vtLine=$($VTOY_PATH/tool/vtoyksym dm_put_table_device $VTOY_PATH/kallsyms)
|
||||
put_addr=$(echo $vtLine | $AWK '{print $1}')
|
||||
put_size=$(echo $vtLine | $AWK '{print $2}')
|
||||
|
||||
ro_addr=$($GREP ' set_memory_ro$' /proc/kallsyms | $AWK '{print $1}')
|
||||
rw_addr=$($GREP ' set_memory_rw$' /proc/kallsyms | $AWK '{print $1}')
|
||||
kprobe_reg_addr=$($GREP ' register_kprobe$' /proc/kallsyms | $AWK '{print $1}')
|
||||
kprobe_unreg_addr=$($GREP ' unregister_kprobe$' /proc/kallsyms | $AWK '{print $1}')
|
||||
|
||||
if [ "$VTOY_DEBUG_LEVEL" = "01" ]; then
|
||||
printk_addr=$($GREP ' printk$' /proc/kallsyms | $AWK '{print $1}')
|
||||
vtDebug="-v"
|
||||
else
|
||||
printk_addr=0
|
||||
fi
|
||||
|
||||
#printk_addr=$($GREP ' printk$' /proc/kallsyms | $AWK '{print $1}')
|
||||
#vtDebug="-v"
|
||||
|
||||
vtlog get_addr=$get_addr get_size=$get_size
|
||||
vtlog put_addr=$put_addr put_size=$put_size
|
||||
vtlog kprobe_reg_addr=$kprobe_reg_addr kprobe_unreg_addr=$kprobe_unreg_addr
|
||||
vtlog ro_addr=$ro_addr rw_addr=$rw_addr printk_addr=$printk_addr
|
||||
|
||||
if [ "$get_addr" = "0" -o "$put_addr" = "0" ]; then
|
||||
vtlog "Invalid symbol address"
|
||||
return
|
||||
fi
|
||||
if [ "$ro_addr" = "0" -o "$rw_addr" = "0" ]; then
|
||||
vtlog "Invalid symbol address"
|
||||
return
|
||||
fi
|
||||
|
||||
|
||||
vtKv=$($BUSYBOX_PATH/uname -r)
|
||||
vtModPath=$($FIND /lib/modules/$vtKv/kernel/fs/ -name "*.ko*" | $HEAD -n1)
|
||||
vtModName=$($BUSYBOX_PATH/basename $vtModPath)
|
||||
|
||||
vtlog "template module is $vtModPath $vtModName"
|
||||
|
||||
if echo $vtModPath | $GREP -q "[.]ko$"; then
|
||||
$BUSYBOX_PATH/cp -a $vtModPath $VTOY_PATH/$vtModName
|
||||
elif echo $vtModPath | $GREP -q "[.]ko[.]xz$"; then
|
||||
$BUSYBOX_PATH/xzcat $vtModPath > $VTOY_PATH/$vtModName
|
||||
elif echo $vtModPath | $GREP -q "[.]ko[.]gz$"; then
|
||||
$BUSYBOX_PATH/zcat $vtModPath > $VTOY_PATH/$vtModName
|
||||
else
|
||||
vtlog "unsupport module type"
|
||||
return
|
||||
fi
|
||||
|
||||
#step1: modify vermagic/mod crc/relocation
|
||||
$VTOY_PATH/tool/vtoykmod -u $VTOY_PATH/tool/$vtKoName $VTOY_PATH/$vtModName $vtDebug
|
||||
|
||||
#step2: fill parameters
|
||||
vtPgsize=$($VTOY_PATH/tool/vtoyksym -p)
|
||||
$VTOY_PATH/tool/vtoykmod -f $VTOY_PATH/tool/$vtKoName $vtPgsize 0x$printk_addr 0x$ro_addr 0x$rw_addr $get_addr $get_size $put_addr $put_size 0x$kprobe_reg_addr 0x$kprobe_unreg_addr $vtDebug
|
||||
|
||||
$BUSYBOX_PATH/insmod $VTOY_PATH/tool/$vtKoName
|
||||
|
||||
if $GREP -q 'dm_patch' /proc/modules; then
|
||||
echo "done" > $VTOY_PATH/dm_patch_done
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
create_ventoy_device_mapper() {
|
||||
vtlog "create_ventoy_device_mapper $*"
|
||||
|
||||
|
@ -238,11 +358,28 @@ create_ventoy_device_mapper() {
|
|||
fi
|
||||
|
||||
$VTOY_PATH/tool/vtoydm -p -f $VTOY_PATH/ventoy_image_map -d $1 > $VTOY_PATH/ventoy_dm_table
|
||||
|
||||
|
||||
vtLevel1=$($CAT /proc/sys/kernel/printk | $AWK '{print $1}')
|
||||
vtLevel2=$($CAT /proc/sys/kernel/printk | $AWK '{print $2}')
|
||||
vtLevel3=$($CAT /proc/sys/kernel/printk | $AWK '{print $3}')
|
||||
vtLevel4=$($CAT /proc/sys/kernel/printk | $AWK '{print $4}')
|
||||
if ventoy_need_dm_patch; then
|
||||
ventoy_dm_patch
|
||||
#suppress printk message
|
||||
echo 0 $vtLevel2 0 $vtLevel4 > /proc/sys/kernel/printk
|
||||
fi
|
||||
|
||||
if [ -z "$2" ]; then
|
||||
$VT_DM_BIN create ventoy $VTOY_PATH/ventoy_dm_table >>$VTLOG 2>&1
|
||||
else
|
||||
$VT_DM_BIN "$2" create ventoy $VTOY_PATH/ventoy_dm_table >>$VTLOG 2>&1
|
||||
fi
|
||||
|
||||
if ventoy_need_dm_patch; then
|
||||
#recover printk level
|
||||
echo $vtLevel1 $vtLevel2 $vtLevel3 $vtLevel4 > /proc/sys/kernel/printk
|
||||
fi
|
||||
}
|
||||
|
||||
create_persistent_device_mapper() {
|
||||
|
@ -263,7 +400,23 @@ create_persistent_device_mapper() {
|
|||
fi
|
||||
|
||||
$VTOY_PATH/tool/vtoydm -p -f $VTOY_PATH/ventoy_persistent_map -d $1 > $VTOY_PATH/persistent_dm_table
|
||||
|
||||
|
||||
vtLevel1=$($CAT /proc/sys/kernel/printk | $AWK '{print $1}')
|
||||
vtLevel2=$($CAT /proc/sys/kernel/printk | $AWK '{print $2}')
|
||||
vtLevel3=$($CAT /proc/sys/kernel/printk | $AWK '{print $3}')
|
||||
vtLevel4=$($CAT /proc/sys/kernel/printk | $AWK '{print $4}')
|
||||
if [ -f $VTOY_PATH/dm_patch_done ]; then
|
||||
#suppress printk message
|
||||
echo 0 $vtLevel2 0 $vtLevel4 > /proc/sys/kernel/printk
|
||||
fi
|
||||
|
||||
$VT_DM_BIN create vtoy_persistent $VTOY_PATH/persistent_dm_table >>$VTLOG 2>&1
|
||||
|
||||
if [ -f $VTOY_PATH/dm_patch_done ]; then
|
||||
#recover printk level
|
||||
echo $vtLevel1 $vtLevel2 $vtLevel3 $vtLevel4 > /proc/sys/kernel/printk
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
|
@ -493,6 +646,22 @@ ventoy_create_persistent_link() {
|
|||
fi
|
||||
}
|
||||
|
||||
ventoy_partname_to_diskname() {
|
||||
if echo $1 | $EGREP -q "nvme.*p[0-9]$|mmc.*p[0-9]$|nbd.*p[0-9]$"; then
|
||||
echo -n "${1:0:-2}"
|
||||
else
|
||||
echo -n "${1:0:-1}"
|
||||
fi
|
||||
}
|
||||
|
||||
ventoy_diskname_to_partname() {
|
||||
if echo $1 | $EGREP -q "nvme.*p[0-9]$|mmc.*p[0-9]$|nbd.*p[0-9]$"; then
|
||||
echo -n "${1}p$2"
|
||||
else
|
||||
echo -n "${1}$2"
|
||||
fi
|
||||
}
|
||||
|
||||
ventoy_udev_disk_common_hook() {
|
||||
if echo $1 | $EGREP -q "nvme.*p[0-9]$|mmc.*p[0-9]$|nbd.*p[0-9]$"; then
|
||||
VTDISK="${1:0:-2}"
|
||||
|
@ -541,6 +710,10 @@ ventoy_udev_disk_common_hook() {
|
|||
create_persistent_device_mapper "/dev/$VTDISK"
|
||||
ventoy_create_persistent_link
|
||||
fi
|
||||
|
||||
if $GREP -q 'dm_patch' /proc/modules; then
|
||||
$BUSYBOX_PATH/rmmod dm_patch
|
||||
fi
|
||||
}
|
||||
|
||||
ventoy_create_dev_ventoy_part() {
|
||||
|
@ -550,6 +723,15 @@ ventoy_create_dev_ventoy_part() {
|
|||
if [ -e /vtoy_dm_table ]; then
|
||||
vtPartid=1
|
||||
|
||||
vtLevel1=$($CAT /proc/sys/kernel/printk | $AWK '{print $1}')
|
||||
vtLevel2=$($CAT /proc/sys/kernel/printk | $AWK '{print $2}')
|
||||
vtLevel3=$($CAT /proc/sys/kernel/printk | $AWK '{print $3}')
|
||||
vtLevel4=$($CAT /proc/sys/kernel/printk | $AWK '{print $4}')
|
||||
if [ -f $VTOY_PATH/dm_patch_done ]; then
|
||||
#suppress printk message
|
||||
echo 0 $vtLevel2 0 $vtLevel4 > /proc/sys/kernel/printk
|
||||
fi
|
||||
|
||||
$CAT /vtoy_dm_table | while read vtline; do
|
||||
echo $vtline > /ventoy/dm_table_part${vtPartid}
|
||||
$VTOY_PATH/tool/dmsetup create ventoy${vtPartid} /ventoy/dm_table_part${vtPartid}
|
||||
|
@ -559,6 +741,11 @@ ventoy_create_dev_ventoy_part() {
|
|||
|
||||
vtPartid=$(expr $vtPartid + 1)
|
||||
done
|
||||
|
||||
if [ -f $VTOY_PATH/dm_patch_done ]; then
|
||||
#recover printk level
|
||||
echo $vtLevel1 $vtLevel2 $vtLevel3 $vtLevel4 > /proc/sys/kernel/printk
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -2022,7 +2022,7 @@ function img_unsupport_menuentry {
|
|||
#############################################################
|
||||
#############################################################
|
||||
|
||||
set VENTOY_VERSION="1.0.63"
|
||||
set VENTOY_VERSION="1.0.64"
|
||||
|
||||
#ACPI not compatible with Window7/8, so disable by default
|
||||
set VTOY_PARAM_NO_ACPI=1
|
||||
|
|
|
@ -505,6 +505,7 @@ int ventoy_data_cmp_control(data_control *data1, data_control *data2)
|
|||
data1->filter_vhd != data2->filter_vhd ||
|
||||
data1->filter_vtoy != data2->filter_vtoy ||
|
||||
data1->win11_bypass_check != data2->win11_bypass_check ||
|
||||
data1->linux_remount != data2->linux_remount ||
|
||||
data1->menu_timeout != data2->menu_timeout)
|
||||
{
|
||||
return 1;
|
||||
|
@ -549,6 +550,7 @@ int ventoy_data_save_control(data_control *data, const char *title, char *buf, i
|
|||
VTOY_JSON_FMT_CTRL_INT(L2, "VTOY_FILE_FLT_VHD", filter_vhd);
|
||||
VTOY_JSON_FMT_CTRL_INT(L2, "VTOY_FILE_FLT_VTOY", filter_vtoy);
|
||||
VTOY_JSON_FMT_CTRL_INT(L2, "VTOY_WIN11_BYPASS_CHECK", win11_bypass_check);
|
||||
VTOY_JSON_FMT_CTRL_INT(L2, "VTOY_LINUX_REMOUNT", linux_remount);
|
||||
VTOY_JSON_FMT_CTRL_INT(L2, "VTOY_MENU_TIMEOUT", menu_timeout);
|
||||
|
||||
VTOY_JSON_FMT_CTRL_STRN(L2, "VTOY_DEFAULT_KBD_LAYOUT", default_kbd_layout);
|
||||
|
@ -593,6 +595,7 @@ int ventoy_data_json_control(data_control *ctrl, char *buf, int buflen)
|
|||
VTOY_JSON_FMT_SINT("filter_vhd", ctrl->filter_vhd);
|
||||
VTOY_JSON_FMT_SINT("filter_vtoy", ctrl->filter_vtoy);
|
||||
VTOY_JSON_FMT_SINT("win11_bypass_check", ctrl->win11_bypass_check);
|
||||
VTOY_JSON_FMT_SINT("linux_remount", ctrl->linux_remount);
|
||||
VTOY_JSON_FMT_SINT("menu_timeout", ctrl->menu_timeout);
|
||||
VTOY_JSON_FMT_STRN("default_kbd_layout", ctrl->default_kbd_layout);
|
||||
VTOY_JSON_FMT_STRN("help_text_language", ctrl->help_text_language);
|
||||
|
@ -658,6 +661,7 @@ static int ventoy_api_save_control(struct mg_connection *conn, VTOY_JSON *json)
|
|||
VTOY_JSON_INT("filter_vhd", ctrl->filter_vhd);
|
||||
VTOY_JSON_INT("filter_vtoy", ctrl->filter_vtoy);
|
||||
VTOY_JSON_INT("win11_bypass_check", ctrl->win11_bypass_check);
|
||||
VTOY_JSON_INT("linux_remount", ctrl->linux_remount);
|
||||
VTOY_JSON_INT("menu_timeout", ctrl->menu_timeout);
|
||||
|
||||
VTOY_JSON_STR("default_image", ctrl->default_image);
|
||||
|
@ -3790,6 +3794,10 @@ static int ventoy_parse_control(VTOY_JSON *json, void *p)
|
|||
{
|
||||
CONTROL_PARSE_INT(child, data->win11_bypass_check);
|
||||
}
|
||||
else if (strcmp(child->pcName, "VTOY_LINUX_REMOUNT") == 0)
|
||||
{
|
||||
CONTROL_PARSE_INT(child, data->linux_remount);
|
||||
}
|
||||
else if (strcmp(child->pcName, "VTOY_TREE_VIEW_MENU_STYLE") == 0)
|
||||
{
|
||||
CONTROL_PARSE_INT(child, data->treeview_style);
|
||||
|
|
|
@ -58,6 +58,7 @@ typedef struct data_control
|
|||
int filter_vtoy;
|
||||
int win11_bypass_check;
|
||||
int menu_timeout;
|
||||
int linux_remount;
|
||||
char default_search_root[MAX_PATH];
|
||||
char default_image[MAX_PATH];
|
||||
char default_kbd_layout[32];
|
||||
|
|
Binary file not shown.
|
@ -1 +1 @@
|
|||
20211203 17:44:10
|
||||
20220108 22:41:02
|
|
@ -723,7 +723,7 @@
|
|||
|
||||
<footer class="main-footer">
|
||||
<div class="pull-right hidden-xs">
|
||||
<b id="plugson_build_date">20211203 17:44:10</b>
|
||||
<b id="plugson_build_date">20220108 22:41:02</b>
|
||||
</div>
|
||||
<strong><a href="https://www.ventoy.net" target="_blank">https://www.ventoy.net</a></strong>
|
||||
</footer>
|
||||
|
|
|
@ -338,6 +338,57 @@
|
|||
|
||||
|
||||
|
||||
<div class="box box-primary box-solid">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title" style="font-size: 14px;font-weight: bold;">VTOY_LINUX_REMOUNT
|
||||
<span id="id_span_desc_cn"> —— Linux 启动后继续访问ISO文件所在分区</span></h3>
|
||||
<div class="box-tools pull-right">
|
||||
<button class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i></button>
|
||||
</div><!-- /.box-tools -->
|
||||
</div><!-- /.box-header -->
|
||||
<div class="box-body no-padding">
|
||||
<table class="table table-bordered no-padding">
|
||||
<tr style="font-weight:bold;">
|
||||
<td class="td_ctrl_col" id="td_title_setting">选项设置</td>
|
||||
<td>
|
||||
<label class="radio-inline">
|
||||
<input type="radio" id="id_ctrl_linux_remount_radio0" name="id_ctrl_linux_remount_radio" data-type="0" value="0"/> <span style="font-weight:bold;">0</span>
|
||||
</label>
|
||||
<label class="radio-inline">
|
||||
<input type="radio" id="id_ctrl_linux_remount_radio1" name="id_ctrl_linux_remount_radio" data-type="1" value="1"/> <span style="font-weight:bold;">1</span>
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="tr_title_desc_cn">
|
||||
<td class="td_ctrl_col" id="td_title_desc">选项说明</td>
|
||||
<td>
|
||||
<code style="font-weight: bold;">0</code> Linux启动后不需要继续访问ISO文件所在的分区。<br/>
|
||||
<code style="font-weight: bold;">1</code> Linux启动后需要继续访问ISO文件所在的分区。<br/><br/>
|
||||
该选项只对 Linux 系统镜像有效。<br/>
|
||||
默认情况下,受Linux内核相关功能的限制,对于Linux系统,在启动后无法继续访问ISO文件所在的分区。在mount的时候会提示 device busy。<br/>
|
||||
如果这里选择 1,则 Ventoy 会尝试通过一些特殊的手段绕过内核的这个限制,但是这个功能是实验性质的,没有经过大规模和长时间的验证。
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="tr_title_desc_en">
|
||||
<td class="td_ctrl_col" id="td_title_desc">Option Description</td>
|
||||
<td>
|
||||
<code style="font-weight: bold;">0</code> I don't need to access the image partition after boot.<br/>
|
||||
<code style="font-weight: bold;">1</code> I need to access the image partition after boot. <br/><br/>
|
||||
This option is only avaliable for Linux distro image files. <br/>
|
||||
|
||||
By default, the image partition where the ISO files locate can not be accessed after boot. When you try to mount it you will get device busy error.
|
||||
This is due to linux kernel restriction (device-mapper module).<br/>
|
||||
If you select 1 here, Ventoy will try to bypass the restriction with some special mechanism.<br/>
|
||||
But it should be noted that, this is an experimental feature and is not fully tested.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div><!-- /.box-body -->
|
||||
</div><!-- /.box -->
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="box box-primary box-solid">
|
||||
<div class="box-header with-border">
|
||||
|
@ -881,6 +932,7 @@
|
|||
var level;
|
||||
|
||||
data.win11_bypass_check = parseInt($('input:radio[name=id_ctrl_bypass_win11_radio]:checked').val());
|
||||
data.linux_remount = parseInt($('input:radio[name=id_ctrl_linux_remount_radio]:checked').val());
|
||||
data.default_search_root = $('input:text[id=id_ctrl_text_search_root]').val();
|
||||
data.menu_timeout = parseInt($('input:text[id=id_ctrl_text_timeout]').val());
|
||||
data.default_image = $('input:text[id=id_ctrl_text_default_img]').val();
|
||||
|
@ -913,6 +965,7 @@
|
|||
function VtoyFillCurrentPageItem(data) {
|
||||
//VTOY_WIN11_BYPASS_CHECK
|
||||
$('input:radio[name=id_ctrl_bypass_win11_radio]')[data.win11_bypass_check].checked = true;
|
||||
$('input:radio[name=id_ctrl_linux_remount_radio]')[data.linux_remount].checked = true;
|
||||
|
||||
//VTOY_DEFAULT_SEARCH_ROOT
|
||||
$('input:text[id=id_ctrl_text_search_root]').val(data.default_search_root);
|
||||
|
@ -1014,6 +1067,7 @@
|
|||
method : 'save_control',
|
||||
index: current_tab_index,
|
||||
win11_bypass_check: data.win11_bypass_check,
|
||||
linux_remount:data.linux_remount,
|
||||
default_search_root: data.default_search_root,
|
||||
menu_timeout: data.menu_timeout,
|
||||
default_image: data.default_image,
|
||||
|
|
|
@ -16,7 +16,7 @@ You can copy many image files at a time and ventoy will give you a boot menu to
|
|||
x86 Legacy BIOS, IA32 UEFI, x86_64 UEFI, ARM64 UEFI and MIPS64EL UEFI are supported in the same way.<br/>
|
||||
Both MBR and GPT partition style are supported in the same way.<br/>
|
||||
Most type of OS supported(Windows/WinPE/Linux/Unix/ChromeOS/Vmware/Xen...) <br/>
|
||||
770+ ISO files are tested (<a href="https://www.ventoy.net/en/isolist.html">List</a>). 90%+ distros in <a href="https://distrowatch.com/">distrowatch.com</a> supported (<a href="https://www.ventoy.net/en/distrowatch.html">Details</a>). <br/>
|
||||
780+ ISO files are tested (<a href="https://www.ventoy.net/en/isolist.html">List</a>). 90%+ distros in <a href="https://distrowatch.com/">distrowatch.com</a> supported (<a href="https://www.ventoy.net/en/distrowatch.html">Details</a>). <br/>
|
||||
<br/>Official Website: <a href=https://www.ventoy.net>https://www.ventoy.net</a>
|
||||
</h4>
|
||||
|
||||
|
@ -58,7 +58,7 @@ A GUI Ventoy plugin configurator. [VentoyPlugson](https://www.ventoy.net/en/plug
|
|||
* FAT32/exFAT/NTFS/UDF/XFS/Ext2(3)(4) supported for main partition
|
||||
* ISO files larger than 4GB supported
|
||||
* Native boot menu style for Legacy & UEFI
|
||||
* Most type of OS supported, 770+ iso files tested
|
||||
* Most type of OS supported, 780+ iso files tested
|
||||
* Linux vDisk boot supported
|
||||
* Not only boot but also complete installation process
|
||||
* Menu dynamically switchable between List/TreeView mode
|
||||
|
|
|
@ -0,0 +1,546 @@
|
|||
/******************************************************************************
|
||||
* vtoykmod.c ---- ventoy kmod
|
||||
*
|
||||
* Copyright (c) 2021, 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define _ull unsigned long long
|
||||
|
||||
#define magic_sig 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF
|
||||
|
||||
#define EI_NIDENT (16)
|
||||
|
||||
#define EI_MAG0 0 /* e_ident[] indexes */
|
||||
#define EI_MAG1 1
|
||||
#define EI_MAG2 2
|
||||
#define EI_MAG3 3
|
||||
#define EI_CLASS 4
|
||||
#define EI_DATA 5
|
||||
#define EI_VERSION 6
|
||||
#define EI_OSABI 7
|
||||
#define EI_PAD 8
|
||||
|
||||
#define ELFMAG0 0x7f /* EI_MAG */
|
||||
#define ELFMAG1 'E'
|
||||
#define ELFMAG2 'L'
|
||||
#define ELFMAG3 'F'
|
||||
#define ELFMAG "\177ELF"
|
||||
#define SELFMAG 4
|
||||
|
||||
#define ELFCLASSNONE 0 /* EI_CLASS */
|
||||
#define ELFCLASS32 1
|
||||
#define ELFCLASS64 2
|
||||
#define ELFCLASSNUM 3
|
||||
|
||||
#define ELFDATANONE 0 /* e_ident[EI_DATA] */
|
||||
#define ELFDATA2LSB 1
|
||||
#define ELFDATA2MSB 2
|
||||
|
||||
#define EV_NONE 0 /* e_version, EI_VERSION */
|
||||
#define EV_CURRENT 1
|
||||
#define EV_NUM 2
|
||||
|
||||
#define ELFOSABI_NONE 0
|
||||
#define ELFOSABI_LINUX 3
|
||||
|
||||
#define SHT_STRTAB 3
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
|
||||
uint16_t e_type; /* Object file type */
|
||||
uint16_t e_machine; /* Architecture */
|
||||
uint32_t e_version; /* Object file version */
|
||||
uint32_t e_entry; /* Entry point virtual address */
|
||||
uint32_t e_phoff; /* Program header table file offset */
|
||||
uint32_t e_shoff; /* Section header table file offset */
|
||||
uint32_t e_flags; /* Processor-specific flags */
|
||||
uint16_t e_ehsize; /* ELF header size in bytes */
|
||||
uint16_t e_phentsize; /* Program header table entry size */
|
||||
uint16_t e_phnum; /* Program header table entry count */
|
||||
uint16_t e_shentsize; /* Section header table entry size */
|
||||
uint16_t e_shnum; /* Section header table entry count */
|
||||
uint16_t e_shstrndx; /* Section header string table index */
|
||||
} Elf32_Ehdr;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
|
||||
uint16_t e_type; /* Object file type */
|
||||
uint16_t e_machine; /* Architecture */
|
||||
uint32_t e_version; /* Object file version */
|
||||
uint64_t e_entry; /* Entry point virtual address */
|
||||
uint64_t e_phoff; /* Program header table file offset */
|
||||
uint64_t e_shoff; /* Section header table file offset */
|
||||
uint32_t e_flags; /* Processor-specific flags */
|
||||
uint16_t e_ehsize; /* ELF header size in bytes */
|
||||
uint16_t e_phentsize; /* Program header table entry size */
|
||||
uint16_t e_phnum; /* Program header table entry count */
|
||||
uint16_t e_shentsize; /* Section header table entry size */
|
||||
uint16_t e_shnum; /* Section header table entry count */
|
||||
uint16_t e_shstrndx; /* Section header string table index */
|
||||
} Elf64_Ehdr;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t sh_name; /* Section name (string tbl index) */
|
||||
uint32_t sh_type; /* Section type */
|
||||
uint32_t sh_flags; /* Section flags */
|
||||
uint32_t sh_addr; /* Section virtual addr at execution */
|
||||
uint32_t sh_offset; /* Section file offset */
|
||||
uint32_t sh_size; /* Section size in bytes */
|
||||
uint32_t sh_link; /* Link to another section */
|
||||
uint32_t sh_info; /* Additional section information */
|
||||
uint32_t sh_addralign; /* Section alignment */
|
||||
uint32_t sh_entsize; /* Entry size if section holds table */
|
||||
} Elf32_Shdr;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t sh_name; /* Section name (string tbl index) */
|
||||
uint32_t sh_type; /* Section type */
|
||||
uint64_t sh_flags; /* Section flags */
|
||||
uint64_t sh_addr; /* Section virtual addr at execution */
|
||||
uint64_t sh_offset; /* Section file offset */
|
||||
uint64_t sh_size; /* Section size in bytes */
|
||||
uint32_t sh_link; /* Link to another section */
|
||||
uint32_t sh_info; /* Additional section information */
|
||||
uint64_t sh_addralign; /* Section alignment */
|
||||
uint64_t sh_entsize; /* Entry size if section holds table */
|
||||
} Elf64_Shdr;
|
||||
|
||||
typedef struct elf32_rel {
|
||||
uint32_t r_offset;
|
||||
uint32_t r_info;
|
||||
} Elf32_Rel;
|
||||
|
||||
typedef struct elf64_rel {
|
||||
uint64_t r_offset; /* Location at which to apply the action */
|
||||
uint64_t r_info; /* index and type of relocation */
|
||||
} Elf64_Rel;
|
||||
|
||||
typedef struct elf32_rela{
|
||||
uint32_t r_offset;
|
||||
uint32_t r_info;
|
||||
int32_t r_addend;
|
||||
} Elf32_Rela;
|
||||
|
||||
typedef struct elf64_rela {
|
||||
uint64_t r_offset; /* Location at which to apply the action */
|
||||
uint64_t r_info; /* index and type of relocation */
|
||||
int64_t r_addend; /* Constant addend used to compute value */
|
||||
} Elf64_Rela;
|
||||
|
||||
|
||||
struct modversion_info {
|
||||
unsigned long crc;
|
||||
char name[64 - sizeof(unsigned long)];
|
||||
};
|
||||
|
||||
|
||||
typedef struct ko_param
|
||||
{
|
||||
unsigned char magic[16];
|
||||
unsigned long struct_size;
|
||||
unsigned long pgsize;
|
||||
unsigned long printk_addr;
|
||||
unsigned long ro_addr;
|
||||
unsigned long rw_addr;
|
||||
unsigned long reg_kprobe_addr;
|
||||
unsigned long unreg_kprobe_addr;
|
||||
unsigned long sym_get_addr;
|
||||
unsigned long sym_get_size;
|
||||
unsigned long sym_put_addr;
|
||||
unsigned long sym_put_size;
|
||||
unsigned long padding[3];
|
||||
}ko_param;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
static int verbose = 0;
|
||||
#define debug(fmt, ...) if(verbose) printf(fmt, ##__VA_ARGS__)
|
||||
|
||||
static int vtoykmod_write_file(char *name, void *buf, int size)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
fp = fopen(name, "wb+");
|
||||
if (!fp)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
fwrite(buf, 1, size, fp);
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vtoykmod_read_file(char *name, char **buf)
|
||||
{
|
||||
int size;
|
||||
FILE *fp;
|
||||
char *databuf;
|
||||
|
||||
fp = fopen(name, "rb");
|
||||
if (!fp)
|
||||
{
|
||||
debug("failed to open %s %d\n", name, errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fseek(fp, 0, SEEK_END);
|
||||
size = (int)ftell(fp);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
|
||||
databuf = malloc(size);
|
||||
if (!databuf)
|
||||
{
|
||||
debug("failed to open malloc %d\n", size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fread(databuf, 1, size, fp);
|
||||
fclose(fp);
|
||||
|
||||
*buf = databuf;
|
||||
return size;
|
||||
}
|
||||
|
||||
static int vtoykmod_find_section64(char *buf, char *section, int *offset, int *len)
|
||||
{
|
||||
uint16_t i;
|
||||
int cmplen;
|
||||
char *name = NULL;
|
||||
char *strtbl = NULL;
|
||||
Elf64_Ehdr *elf = NULL;
|
||||
Elf64_Shdr *sec = NULL;
|
||||
|
||||
cmplen = (int)strlen(section);
|
||||
|
||||
elf = (Elf64_Ehdr *)buf;
|
||||
sec = (Elf64_Shdr *)(buf + elf->e_shoff);
|
||||
strtbl = buf + sec[elf->e_shstrndx].sh_offset;
|
||||
|
||||
for (i = 0; i < elf->e_shnum; i++)
|
||||
{
|
||||
name = strtbl + sec[i].sh_name;
|
||||
if (name && strncmp(name, section, cmplen) == 0)
|
||||
{
|
||||
*offset = (int)(sec[i].sh_offset);
|
||||
*len = (int)(sec[i].sh_size);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int vtoykmod_find_section32(char *buf, char *section, int *offset, int *len)
|
||||
{
|
||||
uint16_t i;
|
||||
int cmplen;
|
||||
char *name = NULL;
|
||||
char *strtbl = NULL;
|
||||
Elf32_Ehdr *elf = NULL;
|
||||
Elf32_Shdr *sec = NULL;
|
||||
|
||||
cmplen = (int)strlen(section);
|
||||
|
||||
elf = (Elf32_Ehdr *)buf;
|
||||
sec = (Elf32_Shdr *)(buf + elf->e_shoff);
|
||||
strtbl = buf + sec[elf->e_shstrndx].sh_offset;
|
||||
|
||||
for (i = 0; i < elf->e_shnum; i++)
|
||||
{
|
||||
name = strtbl + sec[i].sh_name;
|
||||
if (name && strncmp(name, section, cmplen) == 0)
|
||||
{
|
||||
*offset = (int)(sec[i].sh_offset);
|
||||
*len = (int)(sec[i].sh_size);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int vtoykmod_update_modcrc(char *oldmodver, int oldcnt, char *newmodver, int newcnt)
|
||||
{
|
||||
int i, j;
|
||||
struct modversion_info *pold, *pnew;
|
||||
|
||||
pold = (struct modversion_info *)oldmodver;
|
||||
pnew = (struct modversion_info *)newmodver;
|
||||
|
||||
for (i = 0; i < oldcnt; i++)
|
||||
{
|
||||
for (j = 0; j < newcnt; j++)
|
||||
{
|
||||
if (strcmp(pold[i].name, pnew[j].name) == 0)
|
||||
{
|
||||
debug("CRC 0x%08lx --> 0x%08lx %s\n", pold[i].crc, pnew[i].crc, pold[i].name);
|
||||
pold[i].crc = pnew[j].crc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vtoykmod_update_vermagic(char *oldbuf, int oldsize, char *newbuf, int newsize, int *modver)
|
||||
{
|
||||
int i = 0;
|
||||
char *oldver = NULL;
|
||||
char *newver = NULL;
|
||||
|
||||
*modver = 0;
|
||||
|
||||
for (i = 0; i < oldsize - 9; i++)
|
||||
{
|
||||
if (strncmp(oldbuf + i, "vermagic=", 9) == 0)
|
||||
{
|
||||
oldver = oldbuf + i + 9;
|
||||
debug("Find old vermagic at %d <%s>\n", i, oldver);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < newsize - 9; i++)
|
||||
{
|
||||
if (strncmp(newbuf + i, "vermagic=", 9) == 0)
|
||||
{
|
||||
newver = newbuf + i + 9;
|
||||
debug("Find new vermagic at %d <%s>\n", i, newver);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (oldver && newver)
|
||||
{
|
||||
memcpy(oldver, newver, strlen(newver) + 1);
|
||||
if (strstr(newver, "modversions"))
|
||||
{
|
||||
*modver = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vtoykmod_update(char *oldko, char *newko)
|
||||
{
|
||||
int rc = 0;
|
||||
int modver = 0;
|
||||
int oldoff, oldlen;
|
||||
int newoff, newlen;
|
||||
int oldsize, newsize;
|
||||
char *newbuf, *oldbuf;
|
||||
|
||||
oldsize = vtoykmod_read_file(oldko, &oldbuf);
|
||||
newsize = vtoykmod_read_file(newko, &newbuf);
|
||||
if (oldsize < 0 || newsize < 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* 1: update vermagic */
|
||||
vtoykmod_update_vermagic(oldbuf, oldsize, newbuf, newsize, &modver);
|
||||
|
||||
/* 2: update modversion crc */
|
||||
if (modver)
|
||||
{
|
||||
if (oldbuf[EI_CLASS] == ELFCLASS64)
|
||||
{
|
||||
rc = vtoykmod_find_section64(oldbuf, "__versions", &oldoff, &oldlen);
|
||||
rc += vtoykmod_find_section64(newbuf, "__versions", &newoff, &newlen);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = vtoykmod_find_section32(oldbuf, "__versions", &oldoff, &oldlen);
|
||||
rc += vtoykmod_find_section32(newbuf, "__versions", &newoff, &newlen);
|
||||
}
|
||||
|
||||
if (rc == 0)
|
||||
{
|
||||
vtoykmod_update_modcrc(oldbuf + oldoff, oldlen / 64, newbuf + newoff, newlen / 64);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("no need to proc modversions\n");
|
||||
}
|
||||
|
||||
/* 3: update relocate address */
|
||||
if (oldbuf[EI_CLASS] == ELFCLASS64)
|
||||
{
|
||||
Elf64_Rela *oldRela, *newRela;
|
||||
|
||||
rc = vtoykmod_find_section64(oldbuf, ".rela.gnu.linkonce.this_module", &oldoff, &oldlen);
|
||||
rc += vtoykmod_find_section64(newbuf, ".rela.gnu.linkonce.this_module", &newoff, &newlen);
|
||||
if (rc == 0)
|
||||
{
|
||||
oldRela = (Elf64_Rela *)(oldbuf + oldoff);
|
||||
newRela = (Elf64_Rela *)(newbuf + newoff);
|
||||
|
||||
debug("init_module rela: 0x%llx --> 0x%llx\n", (_ull)(oldRela[0].r_offset), (_ull)(newRela[0].r_offset));
|
||||
oldRela[0].r_offset = newRela[0].r_offset;
|
||||
oldRela[0].r_addend = newRela[0].r_addend;
|
||||
|
||||
debug("cleanup_module rela: 0x%llx --> 0x%llx\n", (_ull)(oldRela[1].r_offset), (_ull)(newRela[1].r_offset));
|
||||
oldRela[1].r_offset = newRela[1].r_offset;
|
||||
oldRela[1].r_addend = newRela[1].r_addend;
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("section .rela.gnu.linkonce.this_module not found\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Elf32_Rel *oldRel, *newRel;
|
||||
|
||||
rc = vtoykmod_find_section32(oldbuf, ".rel.gnu.linkonce.this_module", &oldoff, &oldlen);
|
||||
rc += vtoykmod_find_section32(newbuf, ".rel.gnu.linkonce.this_module", &newoff, &newlen);
|
||||
if (rc == 0)
|
||||
{
|
||||
oldRel = (Elf32_Rel *)(oldbuf + oldoff);
|
||||
newRel = (Elf32_Rel *)(newbuf + newoff);
|
||||
|
||||
debug("init_module rel: 0x%x --> 0x%x\n", oldRel[0].r_offset, newRel[0].r_offset);
|
||||
oldRel[0].r_offset = newRel[0].r_offset;
|
||||
|
||||
debug("cleanup_module rel: 0x%x --> 0x%x\n", oldRel[0].r_offset, newRel[0].r_offset);
|
||||
oldRel[1].r_offset = newRel[1].r_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("section .rel.gnu.linkonce.this_module not found\n");
|
||||
}
|
||||
}
|
||||
|
||||
vtoykmod_write_file(oldko, oldbuf, oldsize);
|
||||
|
||||
free(oldbuf);
|
||||
free(newbuf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vtoykmod_fill_param(char **argv)
|
||||
{
|
||||
int i;
|
||||
int size;
|
||||
char *buf = NULL;
|
||||
ko_param *param;
|
||||
unsigned char magic[16] = { magic_sig };
|
||||
|
||||
size = vtoykmod_read_file(argv[0], &buf);
|
||||
if (size < 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
if (memcmp(buf + i, magic, 16) == 0)
|
||||
{
|
||||
debug("Find param magic at %d\n", i);
|
||||
param = (ko_param *)(buf + i);
|
||||
|
||||
param->struct_size = (unsigned long)sizeof(ko_param);
|
||||
param->pgsize = strtoul(argv[1], NULL, 10);
|
||||
param->printk_addr = strtoul(argv[2], NULL, 16);
|
||||
param->ro_addr = strtoul(argv[3], NULL, 16);
|
||||
param->rw_addr = strtoul(argv[4], NULL, 16);
|
||||
param->sym_get_addr = strtoul(argv[5], NULL, 16);
|
||||
param->sym_get_size = strtoul(argv[6], NULL, 10);
|
||||
param->sym_put_addr = strtoul(argv[7], NULL, 16);
|
||||
param->sym_put_size = strtoul(argv[8], NULL, 10);
|
||||
param->reg_kprobe_addr = strtoul(argv[9], NULL, 16);
|
||||
param->unreg_kprobe_addr = strtoul(argv[10], NULL, 16);
|
||||
|
||||
debug("pgsize=%lu (%s)\n", param->pgsize, argv[1]);
|
||||
debug("printk_addr=0x%lx (%s)\n", param->printk_addr, argv[2]);
|
||||
debug("ro_addr=0x%lx (%s)\n", param->ro_addr, argv[3]);
|
||||
debug("rw_addr=0x%lx (%s)\n", param->rw_addr, argv[4]);
|
||||
debug("sym_get_addr=0x%lx (%s)\n", param->sym_get_addr, argv[5]);
|
||||
debug("sym_get_size=%lu (%s)\n", param->sym_get_size, argv[6]);
|
||||
debug("sym_put_addr=0x%lx (%s)\n", param->sym_put_addr, argv[7]);
|
||||
debug("sym_put_size=%lu (%s)\n", param->sym_put_size, argv[8]);
|
||||
debug("reg_kprobe_addr=0x%lx (%s)\n", param->reg_kprobe_addr, argv[9]);
|
||||
debug("unreg_kprobe_addr=0x%lx (%s)\n", param->unreg_kprobe_addr, argv[10]);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= size)
|
||||
{
|
||||
debug("### param magic not found \n");
|
||||
}
|
||||
|
||||
vtoykmod_write_file(argv[0], buf, size);
|
||||
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vtoykmod_main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
if (argv[i][0] == '-' && argv[i][1] == 'v')
|
||||
{
|
||||
verbose = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (argv[1][0] == '-' && argv[1][1] == 'f')
|
||||
{
|
||||
return vtoykmod_fill_param(argv + 2);
|
||||
}
|
||||
else if (argv[1][0] == '-' && argv[1][1] == 'u')
|
||||
{
|
||||
return vtoykmod_update(argv[2], argv[3]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// wrapper main
|
||||
#ifndef BUILD_VTOY_TOOL
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
return vtoykmod_main(argc, argv);
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
/******************************************************************************
|
||||
* vtoyksym.c ---- ventoy ksym
|
||||
*
|
||||
* Copyright (c) 2021, 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static int verbose = 0;
|
||||
#define debug(fmt, ...) if(verbose) printf(fmt, ##__VA_ARGS__)
|
||||
|
||||
int vtoyksym_main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
unsigned long long addr1 = 0;
|
||||
unsigned long long addr2 = 0;
|
||||
char sym[256];
|
||||
char line[1024];
|
||||
const char *name = NULL;
|
||||
FILE *fp;
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
if (argv[i][0] == '-' && argv[i][1] == 'p')
|
||||
{
|
||||
printf("%d", getpagesize());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
if (argv[i][0] == '-' && argv[i][1] == 'v')
|
||||
{
|
||||
verbose = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
name = argv[2] ? argv[2] : "/proc/kallsyms";
|
||||
fp = fopen(name, "r");
|
||||
if (!fp)
|
||||
{
|
||||
fprintf(stderr, "Failed to open file %s err:%d\n", name, errno);
|
||||
return 1;
|
||||
}
|
||||
|
||||
debug("open %s success\n", name);
|
||||
|
||||
snprintf(sym, sizeof(sym), " %s", argv[1]);
|
||||
debug("lookup for <%s>\n", sym);
|
||||
|
||||
while (fgets(line, sizeof(line), fp))
|
||||
{
|
||||
if (strstr(line, sym))
|
||||
{
|
||||
addr1 = strtoull(line, NULL, 16);
|
||||
if (!fgets(line, sizeof(line), fp))
|
||||
{
|
||||
addr1 = 0;
|
||||
fprintf(stderr, "Failed to read next line\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
addr2 = strtoull(line, NULL, 16);
|
||||
}
|
||||
|
||||
debug("addr1=<0x%llx> addr2=<0x%llx>\n", addr1, addr2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (addr1 > addr2)
|
||||
{
|
||||
debug("Invalid addr range\n");
|
||||
printf("0 0\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("0x%llx %llu\n", addr1, addr2 - addr1);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// wrapper main
|
||||
#ifndef BUILD_VTOY_TOOL
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
return vtoyksym_main(argc, argv);
|
||||
}
|
||||
#endif
|
||||
|
|
@ -36,6 +36,8 @@ int vtoydm_main(int argc, char **argv);
|
|||
int vtoytool_install(int argc, char **argv);
|
||||
int vtoyloader_main(int argc, char **argv);
|
||||
int vtoyvine_main(int argc, char **argv);
|
||||
int vtoyksym_main(int argc, char **argv);
|
||||
int vtoykmod_main(int argc, char **argv);
|
||||
|
||||
static char *g_vtoytool_name = NULL;
|
||||
static cmd_def g_cmd_list[] =
|
||||
|
@ -44,6 +46,8 @@ static cmd_def g_cmd_list[] =
|
|||
{ "vtoydump", vtoydump_main },
|
||||
{ "vtoydm", vtoydm_main },
|
||||
{ "loader", vtoyloader_main },
|
||||
{ "vtoyksym", vtoyksym_main },
|
||||
{ "vtoykmod", vtoykmod_main },
|
||||
{ "--install", vtoytool_install },
|
||||
};
|
||||
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue