Compare commits
107 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
d8fbd79dda | ||
|
8c192a1807 | ||
|
e8d17f9bb1 | ||
|
2283c3e8b0 | ||
|
8bbd5a14a3 | ||
|
f7d7db6a18 | ||
|
147a23c9dd | ||
|
062c71b972 | ||
|
78ab7a0759 | ||
|
3ebd58c9df | ||
|
ce6d379564 | ||
|
40fdfa66b9 | ||
|
9ddee7394d | ||
|
c9b316a757 | ||
|
1ba23bcdff | ||
|
6630ab3585 | ||
|
c0d478c2dd | ||
|
0217c5a923 | ||
|
97312d351e | ||
|
906dc4cd41 | ||
|
82a8b59bc7 | ||
|
b53e1fb8a8 | ||
|
84abffc424 | ||
|
bf4e014023 | ||
|
4f840ed673 | ||
|
d02f184a8d | ||
|
774e38928f | ||
|
0faba673a5 | ||
|
3c649b281f | ||
|
5f409a1208 | ||
|
9eb334d99a | ||
|
260a3269b7 | ||
|
a287bf8907 | ||
|
48a1b80be0 | ||
|
b9ef72fbe9 | ||
|
390507fff7 | ||
|
a29bdfbc3c | ||
|
21735f92d6 | ||
|
9a8d4d0227 | ||
|
6ebe77792c | ||
|
d678e54956 | ||
|
8dce0adda6 | ||
|
1bf3e73373 | ||
|
a9996d6761 | ||
|
dafea731c8 | ||
|
6d093e88e7 | ||
|
58a93cdb40 | ||
|
9962775296 | ||
|
062f816020 | ||
|
89b7232b76 | ||
|
1186caba41 | ||
|
be50ea69aa | ||
|
433d854aab | ||
|
4cb9134e5c | ||
|
faceaf4267 | ||
|
37edd5a349 | ||
|
ed0f8721d7 | ||
|
d80a008c04 | ||
|
036e9cc167 | ||
|
26258653b7 | ||
|
754e754412 | ||
|
5af01de7c2 | ||
|
f9763a44b2 | ||
|
d063dbb7f2 | ||
|
89938e3c78 | ||
|
85840f626b | ||
|
7d1507906d | ||
|
0f8478fbe1 | ||
|
a6d3ecc7a9 | ||
|
5817b8b7b0 | ||
|
8493715fb4 | ||
|
3c46432d6f | ||
|
88dcceeabc | ||
|
ef204263ad | ||
|
e08e6705cf | ||
|
a8b2fdccc7 | ||
|
85348956df | ||
|
aa0a2ed067 | ||
|
49ceaa0f61 | ||
|
23986d742d | ||
|
039e68400d | ||
|
e384dad4d0 | ||
|
dcb3264519 | ||
|
4fda20d844 | ||
|
b32cf97f1f | ||
|
f7b35f371b | ||
|
49ca1e05a4 | ||
|
9ecbff9ce6 | ||
|
1d034f0a24 | ||
|
0ddc76a3aa | ||
|
a1ddade13c | ||
|
b925bbdeec | ||
|
e91b315f09 | ||
|
1cbe4c81b4 | ||
|
42990058ed | ||
|
171667c547 | ||
|
a5c706511b | ||
|
785255b65f | ||
|
176c819d10 | ||
|
8f2bf03084 | ||
|
4408be5cf0 | ||
|
74154ad9a3 | ||
|
43fcd4f262 | ||
|
be35990666 | ||
|
ad3db3dfcb | ||
|
227264f208 | ||
|
1f37663285 |
24
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
name: Ventoy CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Run docker-compose up
|
||||
run: docker-compose up
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ventoy-linux
|
||||
path: INSTALL/ventoy-*linux*
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ventoy-windows
|
||||
path: INSTALL/ventoy-*windows*
|
||||
|
1166
BUSYBOX/64h.config
Normal file
18
BUSYBOX/chmod/build.sh
Normal file
@@ -0,0 +1,18 @@
|
||||
#!/bin/sh
|
||||
|
||||
DSTDIR=../../IMG/cpio/ventoy/busybox
|
||||
|
||||
rm -f vtchmod32 vtchmod64
|
||||
rm -f $DSTDIR/vtchmod32 $DSTDIR/vtchmod64
|
||||
|
||||
/opt/diet32/bin/diet gcc -Os -m32 vtchmod.c -o vtchmod32
|
||||
/opt/diet64/bin/diet gcc -Os vtchmod.c -o vtchmod64
|
||||
|
||||
chmod 777 vtchmod32
|
||||
chmod 777 vtchmod64
|
||||
|
||||
cp -a vtchmod32 $DSTDIR/
|
||||
cp -a vtchmod64 $DSTDIR/
|
||||
|
||||
|
||||
|
13
BUSYBOX/chmod/vtchmod.c
Normal file
@@ -0,0 +1,13 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc != 2)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return chmod(argv[1], 0777);
|
||||
}
|
||||
|
BIN
BUSYBOX/chmod/vtchmod32
Normal file
BIN
BUSYBOX/chmod/vtchmod64
Normal file
@@ -28,4 +28,22 @@ build for 32bit, static linked with dietlibc
|
||||
|
||||
4. make
|
||||
5. strip dmsetup/dmsetup
|
||||
5. get dmsetup/dmsetup as the binary file
|
||||
6. get dmsetup/dmsetup as the dmsetup32 binary file
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
======================== Build for 64bit dmsetup =========================
|
||||
https://www.uclibc.org/downloads/binaries/0.9.30.1/mini-native-x86_64.tar.bz2
|
||||
1. extract device mapper source code
|
||||
2. extract mini-native-x86_64.tar.bz2
|
||||
3. chroot to mini-native-x86_64
|
||||
3. ./configure --disable-nls --disable-selinux --disable-shared --enable-static_link
|
||||
4. make
|
||||
5. strip dmsetup/dmsetup.static
|
||||
6. get dmsetup/dmsetup.static as the dmsetup64 binary file
|
||||
|
||||
|
||||
|
||||
|
BIN
DMSETUP/dmsetup64
Normal file
@@ -3,7 +3,7 @@
|
||||
1. Compile Enviroment
|
||||
==========================================
|
||||
My build envrioment is CentOS 7.8 x86_64. So here I first explain how to create the build environment from scratch.
|
||||
Because Ventoy is based on many open source projects, so the envrioment is important. I suggest you test it on a virtual machine first.
|
||||
Because Ventoy is based on many open source projects, so the environment is important. I suggest you test it on a virtual machine first.
|
||||
|
||||
1.1 Install CentOS 7.8
|
||||
I use CentOS-7-x86_64-Everything-2003.iso and select Minimal install
|
||||
@@ -31,7 +31,6 @@
|
||||
https://codeload.github.com/tianocore/edk2/zip/edk2-stable201911 ===> /home/Ventoy-master/EDK2/edk2-edk2-stable201911.zip
|
||||
https://codeload.github.com/relan/exfat/zip/v1.3.0 ===> /home/Ventoy-master/ExFAT/exfat-1.3.0.zip
|
||||
https://codeload.github.com/libfuse/libfuse/zip/fuse-2.9.9 ===> /home/Ventoy-master/ExFAT/libfuse-fuse-2.9.9.zip
|
||||
http://ultra-embedded.com/releases/fat_io_lib.zip ===> /home/Ventoy-master/vtoyfat/fat_io_lib/fat_io_lib.zip
|
||||
|
||||
|
||||
|
||||
@@ -128,15 +127,32 @@
|
||||
cd /home/Ventoy-master/GenUUID
|
||||
sh build.sh
|
||||
|
||||
4.15 == Build xzminidec ==
|
||||
cd /home/Ventoy-master/xz-embedded-20130513/userspace
|
||||
4.15 == Build xzminidec32 ==
|
||||
cd /home/Ventoy-master/Ventoy2Disk/Ventoy2Disk/xz-embedded-20130513/userspace
|
||||
make -f ventoy_makefile
|
||||
strip --strip-all xzminidec
|
||||
|
||||
4.16 == Build iso9660_x64.efi ==
|
||||
|
||||
4.16 == Build xzminidec64 ==
|
||||
cd /home/Ventoy-master/Ventoy2Disk/Ventoy2Disk/xz-embedded-20130513/userspace
|
||||
make -f ventoy_makefile64
|
||||
strip --strip-all xzminidec
|
||||
|
||||
4.17 == Build iso9660_x64.efi ==
|
||||
This efi driver is from https://github.com/pbatard/efifs
|
||||
Follow all the build instructions in this project. I modified 3 files (the original and modified source are at /home/Ventoy-master/EDK2/efiffs)
|
||||
|
||||
4.18 IMG/cpio/ventoy/busybox/64h
|
||||
https://www.uclibc.org/downloads/binaries/0.9.30.1/mini-native-x86_64.tar.bz2
|
||||
https://busybox.net/downloads/busybox-1.32.0.tar.bz2
|
||||
use BUSYBOX/64h.config and uclibc to build busybox-1.32
|
||||
|
||||
4.19 == Build lunzip32/lunzip64 ==
|
||||
http://mirror.yongbok.net/nongnu/lzip/lunzip/lunzip-1.11.tar.gz
|
||||
PATH=$PATH:/opt/diet/bin
|
||||
./configure --disable-nls CC='diet gcc -nostdinc'
|
||||
make
|
||||
strip --strip-all lunzip
|
||||
|
||||
|
||||
|
||||
==========================================
|
||||
@@ -157,7 +173,7 @@
|
||||
https://busybox.net/downloads/binaries/1.30.0-i686 busybox_INOTIFYD
|
||||
SHA-256: 3532162a8695e91a1ed9ddea28b2cb22259a90e93d5d9c4a517b6c36842c686f
|
||||
|
||||
5.4 IMG/cpio/ventoy/busybox/tmpsh
|
||||
5.4 IMG/cpio/ventoy/busybox/ash
|
||||
https://busybox.net/downloads/binaries/1.27.1-i686 busybox_ASH
|
||||
SHA-256: 44a6274bca580c2758ffc173fc76d18bb855b1fe8dcf70efd9ee75cbd57dee97
|
||||
|
||||
@@ -199,5 +215,14 @@
|
||||
INSTALL/EFI/BOOT/MokManager.efi --> EFI/BOOT/MokManager.efi SHA-256: 3bf1f46cee0832355c7dd1dba880dea9bcaa78cc44375a1559d43bc9db18933b
|
||||
|
||||
|
||||
5.11 INSTALL/tool/ash
|
||||
https://busybox.net/downloads/binaries/1.31.0-i686-uclibc/ busybox_ASH
|
||||
SHA-256: 2943f02f85fee0c9551aec47110a558a73f919c032b3c51e56d6f197b5ec4d7b
|
||||
|
||||
|
||||
5.12 7za.exe
|
||||
download from https://www.7-zip.org/a/7z1900-extra.7z
|
||||
ISNTALL/ventoy/7z/64/7za.exe SHA-256: 8117e40ee7f824f63373a4f5625bb62749f69159d0c449b3ce2f35aad3b83549
|
||||
ISNTALL/ventoy/7z/32/7za.exe SHA-256: ea308c76a2f927b160a143d94072b0dce232e04b751f0c6432a94e05164e716d
|
||||
|
||||
|
||||
|
||||
|
29
DOC/LoopExBuild.txt
Normal file
@@ -0,0 +1,29 @@
|
||||
|
||||
1. LAKKA dm-mod.ko
|
||||
LaKKa config
|
||||
https://github.com/libretro/Lakka-LibreELEC/releases download source code
|
||||
\projects\Generic\linux\linux.x86_64.conf
|
||||
|
||||
Linux Kernel
|
||||
linux-4.11.12.tar.xz & patch-4.11.12-rt14.patch.xz
|
||||
patch -p1 < ../patch-4.11.12-rt14
|
||||
|
||||
make menuconfig
|
||||
select device mapper as module
|
||||
make -j 16
|
||||
get drivers\md\dm-mod.ko
|
||||
|
||||
2. LibreELEC dm-mod.ko
|
||||
LibreELEC config
|
||||
https://github.com/LibreELEC/LibreELEC.tv/releases download source code
|
||||
\projects\Generic\linux\linux.x86_64.conf
|
||||
|
||||
Linux Kernel
|
||||
linux-5.1.6.tar.xz
|
||||
make menuconfig
|
||||
select device mapper as module
|
||||
make -j 16
|
||||
get drivers\md\dm-mod.ko
|
||||
|
||||
|
||||
|
17
Dockerfile
Normal file
@@ -0,0 +1,17 @@
|
||||
FROM centos:7
|
||||
|
||||
RUN yum -y install \
|
||||
libXpm net-tools bzip2 wget vim gcc gcc-c++ samba dos2unix glibc-devel glibc.i686 glibc-devel.i686 \
|
||||
mpfr.i686 mpfr-devel.i686 zlib.i686 rsync autogen autoconf automake libtool gettext* bison binutils \
|
||||
flex device-mapper-devel SDL libpciaccess libusb freetype freetype-devel gnu-free-* qemu-* virt-* \
|
||||
libvirt* vte* NetworkManager-bluetooth brlapi fuse-devel dejavu* gnu-efi* pesign shim \
|
||||
iscsi-initiator-utils grub2-tools zip nasm acpica-tools glibc-static zlib-static
|
||||
|
||||
CMD cd /ventoy \
|
||||
&& wget -P DOC/ https://www.fefe.de/dietlibc/dietlibc-0.34.tar.xz \
|
||||
&& wget -P GRUB2/ https://ftp.gnu.org/gnu/grub/grub-2.04.tar.xz \
|
||||
&& wget -O EDK2/edk2-edk2-stable201911.zip https://codeload.github.com/tianocore/edk2/zip/edk2-stable201911 \
|
||||
&& wget -O ExFAT/exfat-1.3.0.zip https://codeload.github.com/relan/exfat/zip/v1.3.0 \
|
||||
&& wget -O ExFAT/libfuse-fuse-2.9.9.zip https://codeload.github.com/libfuse/libfuse/zip/fuse-2.9.9 \
|
||||
&& cd INSTALL && ls -la && sh all_in_one.sh
|
||||
|
@@ -25,6 +25,15 @@
|
||||
|
||||
#define VENTOY_GUID { 0x77772020, 0x2e77, 0x6576, { 0x6e, 0x74, 0x6f, 0x79, 0x2e, 0x6e, 0x65, 0x74 }}
|
||||
|
||||
typedef enum ventoy_chain_type
|
||||
{
|
||||
ventoy_chain_linux = 0, /* 0: linux */
|
||||
ventoy_chain_windows, /* 1: windows */
|
||||
ventoy_chain_wim, /* 2: wim */
|
||||
|
||||
ventoy_chain_max
|
||||
}ventoy_chain_type;
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
typedef struct ventoy_guid
|
||||
@@ -159,6 +168,8 @@ typedef struct ventoy_virt_chunk
|
||||
#define VTOY_BLOCK_DEVICE_PATH_GUID \
|
||||
{ 0x37b87ac6, 0xc180, 0x4583, { 0xa7, 0x05, 0x41, 0x4d, 0xa8, 0xf7, 0x7e, 0xd2 }}
|
||||
|
||||
#define ISO9660_EFI_DRIVER_PATH L"\\ventoy\\iso9660_x64.efi"
|
||||
|
||||
#define VTOY_BLOCK_DEVICE_PATH_NAME L"ventoy"
|
||||
|
||||
#if defined (MDE_CPU_IA32)
|
||||
@@ -174,6 +185,9 @@ typedef struct ventoy_virt_chunk
|
||||
#error Unknown Processor Type
|
||||
#endif
|
||||
|
||||
#define VENTOY_DEVICE_WARN 1
|
||||
#define VTOY_WARNING L"!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!"
|
||||
|
||||
typedef struct ventoy_sector_flag
|
||||
{
|
||||
UINT8 flag; // 0:init 1:mem 2:remap
|
||||
@@ -202,7 +216,6 @@ typedef struct vtoy_block_data
|
||||
EFI_HANDLE IsoDriverImage;
|
||||
}vtoy_block_data;
|
||||
|
||||
#define ISO9660_EFI_DRIVER_PATH L"\\ventoy\\iso9660_x64.efi"
|
||||
|
||||
#define debug(expr, ...) if (gDebugPrint) VtoyDebug("[VTOY] "expr"\r\n", ##__VA_ARGS__)
|
||||
#define trace(expr, ...) VtoyDebug("[VTOY] "expr"\r\n", ##__VA_ARGS__)
|
||||
@@ -217,7 +230,9 @@ if (gDebugPrint) \
|
||||
gBS->WaitForEvent(1, &gST->ConIn->WaitForKey, &__Index);\
|
||||
}
|
||||
|
||||
typedef int (*grub_env_set_pf)(const char *name, const char *val);
|
||||
typedef const char * (*grub_env_get_pf)(const char *name);
|
||||
typedef int (*grub_env_printf_pf)(const char *fmt, ...);
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
@@ -244,8 +259,9 @@ typedef struct ventoy_grub_param_file_replace
|
||||
typedef struct ventoy_grub_param
|
||||
{
|
||||
grub_env_get_pf grub_env_get;
|
||||
|
||||
grub_env_set_pf grub_env_set;
|
||||
ventoy_grub_param_file_replace file_replace;
|
||||
grub_env_printf_pf grub_env_printf;
|
||||
}ventoy_grub_param;
|
||||
|
||||
typedef struct ventoy_ram_disk
|
||||
@@ -254,6 +270,40 @@ typedef struct ventoy_ram_disk
|
||||
UINT64 DiskSize;
|
||||
}ventoy_ram_disk;
|
||||
|
||||
typedef struct ventoy_iso9660_override
|
||||
{
|
||||
UINT32 first_sector;
|
||||
UINT32 first_sector_be;
|
||||
UINT32 size;
|
||||
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()
|
||||
|
||||
|
||||
@@ -273,6 +323,18 @@ typedef struct ventoy_system_wrapper
|
||||
|
||||
EFI_OPEN_PROTOCOL NewOpenProtocol;
|
||||
EFI_OPEN_PROTOCOL OriOpenProtocol;
|
||||
|
||||
EFI_LOCATE_HANDLE_BUFFER NewLocateHandleBuffer;
|
||||
EFI_LOCATE_HANDLE_BUFFER OriLocateHandleBuffer;
|
||||
|
||||
EFI_PROTOCOLS_PER_HANDLE NewProtocolsPerHandle;
|
||||
EFI_PROTOCOLS_PER_HANDLE OriProtocolsPerHandle;
|
||||
|
||||
EFI_LOCATE_HANDLE NewLocateHandle;
|
||||
EFI_LOCATE_HANDLE OriLocateHandle;
|
||||
|
||||
EFI_LOCATE_DEVICE_PATH NewLocateDevicePath;
|
||||
EFI_LOCATE_DEVICE_PATH OriLocateDevicePath;
|
||||
} ventoy_system_wrapper;
|
||||
|
||||
#define ventoy_wrapper(bs, wrapper, func, newfunc) \
|
||||
@@ -282,11 +344,9 @@ typedef struct ventoy_system_wrapper
|
||||
bs->func = wrapper.New##func;\
|
||||
}
|
||||
|
||||
extern ventoy_efi_file_replace g_efi_file_replace;
|
||||
extern BOOLEAN gDebugPrint;
|
||||
VOID EFIAPI VtoyDebug(IN CONST CHAR8 *Format, ...);
|
||||
EFI_STATUS EFIAPI ventoy_wrapper_system(VOID);
|
||||
EFI_STATUS EFIAPI ventoy_wrapper_file_procotol(EFI_FILE_PROTOCOL *File);
|
||||
EFI_STATUS EFIAPI ventoy_block_io_read
|
||||
(
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
@@ -296,5 +356,39 @@ EFI_STATUS EFIAPI ventoy_block_io_read
|
||||
OUT VOID *Buffer
|
||||
);
|
||||
|
||||
|
||||
extern ventoy_chain_head *g_chain;
|
||||
extern ventoy_img_chunk *g_chunk;
|
||||
extern UINT32 g_img_chunk_num;
|
||||
extern ventoy_override_chunk *g_override_chunk;
|
||||
extern UINT32 g_override_chunk_num;
|
||||
extern ventoy_virt_chunk *g_virt_chunk;
|
||||
extern UINT32 g_virt_chunk_num;
|
||||
extern vtoy_block_data gBlockData;
|
||||
extern ventoy_efi_file_replace g_efi_file_replace;
|
||||
extern ventoy_sector_flag *g_sector_flag;
|
||||
extern UINT32 g_sector_flag_num;
|
||||
extern BOOLEAN gMemdiskMode;
|
||||
extern BOOLEAN gSector512Mode;
|
||||
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;
|
||||
extern BOOLEAN g_fix_windows_1st_cdrom_issue;
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_wrapper_open_volume
|
||||
(
|
||||
IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
|
||||
OUT EFI_FILE_PROTOCOL **Root
|
||||
);
|
||||
EFI_STATUS EFIAPI ventoy_install_blockio(IN EFI_HANDLE ImageHandle, IN UINT64 ImgSize);
|
||||
EFI_STATUS EFIAPI ventoy_wrapper_push_openvolume(IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME OpenVolume);
|
||||
EFI_STATUS ventoy_hook_keyboard_start(VOID);
|
||||
EFI_STATUS ventoy_hook_keyboard_stop(VOID);
|
||||
BOOLEAN ventoy_is_cdrom_dp_exist(VOID);
|
||||
EFI_STATUS ventoy_hook_1st_cdrom_start(VOID);
|
||||
EFI_STATUS ventoy_hook_1st_cdrom_stop(VOID);
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -29,6 +29,7 @@
|
||||
Ventoy.h
|
||||
Ventoy.c
|
||||
VentoyDebug.c
|
||||
VentoyProtocol.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
|
@@ -36,6 +36,10 @@
|
||||
#include <Protocol/SimpleFileSystem.h>
|
||||
#include <Ventoy.h>
|
||||
|
||||
#define PROCOTOL_SLEEP_MSECONDS 0
|
||||
|
||||
#define debug_sleep() if (PROCOTOL_SLEEP_MSECONDS) gBS->Stall(1000 * PROCOTOL_SLEEP_MSECONDS)
|
||||
|
||||
STATIC ventoy_system_wrapper g_system_wrapper;
|
||||
|
||||
static struct well_known_guid g_efi_well_known_guids[] =
|
||||
@@ -84,183 +88,6 @@ static const char * ventoy_get_guid_name(EFI_GUID *guid)
|
||||
return gEfiGuidName;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_fs_open(EFI_FILE_HANDLE This, EFI_FILE_HANDLE *New, CHAR16 *Name, UINT64 Mode, UINT64 Attributes)
|
||||
{
|
||||
(VOID)This;
|
||||
(VOID)New;
|
||||
(VOID)Name;
|
||||
(VOID)Mode;
|
||||
(VOID)Attributes;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_open_ex(EFI_FILE_HANDLE This, EFI_FILE_HANDLE *New, CHAR16 *Name, UINT64 Mode, UINT64 Attributes, EFI_FILE_IO_TOKEN *Token)
|
||||
{
|
||||
return ventoy_wrapper_fs_open(This, New, Name, Mode, Attributes);
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_delete(EFI_FILE_HANDLE This)
|
||||
{
|
||||
(VOID)This;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_set_info(EFI_FILE_HANDLE This, EFI_GUID *Type, UINTN Len, VOID *Data)
|
||||
{
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_flush(EFI_FILE_HANDLE This)
|
||||
{
|
||||
(VOID)This;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/* Ex version */
|
||||
EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_flush_ex(EFI_FILE_HANDLE This, EFI_FILE_IO_TOKEN *Token)
|
||||
{
|
||||
(VOID)This;
|
||||
(VOID)Token;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_write(EFI_FILE_HANDLE This, UINTN *Len, VOID *Data)
|
||||
{
|
||||
(VOID)This;
|
||||
(VOID)Len;
|
||||
(VOID)Data;
|
||||
|
||||
return EFI_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_write_ex(IN EFI_FILE_PROTOCOL *This, IN OUT EFI_FILE_IO_TOKEN *Token)
|
||||
{
|
||||
return ventoy_wrapper_file_write(This, &(Token->BufferSize), Token->Buffer);
|
||||
}
|
||||
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_close(EFI_FILE_HANDLE This)
|
||||
{
|
||||
(VOID)This;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_set_pos(EFI_FILE_HANDLE This, UINT64 Position)
|
||||
{
|
||||
(VOID)This;
|
||||
|
||||
g_efi_file_replace.CurPos = Position;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_get_pos(EFI_FILE_HANDLE This, UINT64 *Position)
|
||||
{
|
||||
(VOID)This;
|
||||
|
||||
*Position = g_efi_file_replace.CurPos;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_get_info(EFI_FILE_HANDLE This, EFI_GUID *Type, UINTN *Len, VOID *Data)
|
||||
{
|
||||
EFI_FILE_INFO *Info = (EFI_FILE_INFO *) Data;
|
||||
|
||||
debug("ventoy_wrapper_file_get_info ... %u", *Len);
|
||||
|
||||
if (!CompareGuid(Type, &gEfiFileInfoGuid))
|
||||
{
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (*Len == 0)
|
||||
{
|
||||
*Len = 384;
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
ZeroMem(Data, sizeof(EFI_FILE_INFO));
|
||||
|
||||
Info->Size = sizeof(EFI_FILE_INFO);
|
||||
Info->FileSize = g_efi_file_replace.FileSizeBytes;
|
||||
Info->PhysicalSize = g_efi_file_replace.FileSizeBytes;
|
||||
Info->Attribute = EFI_FILE_READ_ONLY;
|
||||
//Info->FileName = EFI_FILE_READ_ONLY;
|
||||
|
||||
*Len = Info->Size;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_read(EFI_FILE_HANDLE This, UINTN *Len, VOID *Data)
|
||||
{
|
||||
EFI_LBA Lba;
|
||||
UINTN ReadLen = *Len;
|
||||
|
||||
(VOID)This;
|
||||
|
||||
debug("ventoy_wrapper_file_read ... %u", *Len);
|
||||
|
||||
if (g_efi_file_replace.CurPos + ReadLen > g_efi_file_replace.FileSizeBytes)
|
||||
{
|
||||
ReadLen = g_efi_file_replace.FileSizeBytes - g_efi_file_replace.CurPos;
|
||||
}
|
||||
|
||||
Lba = g_efi_file_replace.CurPos / 2048 + g_efi_file_replace.BlockIoSectorStart;
|
||||
|
||||
ventoy_block_io_read(NULL, 0, Lba, ReadLen, Data);
|
||||
|
||||
*Len = ReadLen;
|
||||
|
||||
g_efi_file_replace.CurPos += ReadLen;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_read_ex(IN EFI_FILE_PROTOCOL *This, IN OUT EFI_FILE_IO_TOKEN *Token)
|
||||
{
|
||||
return ventoy_wrapper_file_read(This, &(Token->BufferSize), Token->Buffer);
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_wrapper_file_procotol(EFI_FILE_PROTOCOL *File)
|
||||
{
|
||||
File->Revision = EFI_FILE_PROTOCOL_REVISION2;
|
||||
File->Open = ventoy_wrapper_fs_open;
|
||||
File->Close = ventoy_wrapper_file_close;
|
||||
File->Delete = ventoy_wrapper_file_delete;
|
||||
File->Read = ventoy_wrapper_file_read;
|
||||
File->Write = ventoy_wrapper_file_write;
|
||||
File->GetPosition = ventoy_wrapper_file_get_pos;
|
||||
File->SetPosition = ventoy_wrapper_file_set_pos;
|
||||
File->GetInfo = ventoy_wrapper_file_get_info;
|
||||
File->SetInfo = ventoy_wrapper_file_set_info;
|
||||
File->Flush = ventoy_wrapper_file_flush;
|
||||
File->OpenEx = ventoy_wrapper_file_open_ex;
|
||||
File->ReadEx = ventoy_wrapper_file_read_ex;
|
||||
File->WriteEx = ventoy_wrapper_file_write_ex;
|
||||
File->FlushEx = ventoy_wrapper_file_flush_ex;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
STATIC EFI_STATUS EFIAPI ventoy_handle_protocol
|
||||
(
|
||||
IN EFI_HANDLE Handle,
|
||||
@@ -270,7 +97,7 @@ STATIC EFI_STATUS EFIAPI ventoy_handle_protocol
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
|
||||
debug("ventoy_handle_protocol:%a", ventoy_get_guid_name(Protocol));
|
||||
debug("ventoy_handle_protocol:%a", ventoy_get_guid_name(Protocol)); debug_sleep();
|
||||
Status = g_system_wrapper.OriHandleProtocol(Handle, Protocol, Interface);
|
||||
|
||||
if (CompareGuid(Protocol, &gEfiSimpleFileSystemProtocolGuid))
|
||||
@@ -280,7 +107,7 @@ STATIC EFI_STATUS EFIAPI ventoy_handle_protocol
|
||||
|
||||
pFile->OpenVolume(pFile, &FileProtocol);
|
||||
|
||||
debug("Handle FS Protocol: %p OpenVolume:%p, FileProtocol:%p, Open:%p",
|
||||
trace("Handle FS Protocol: %p OpenVolume:%p, FileProtocol:%p, Open:%p",
|
||||
pFile, pFile->OpenVolume, FileProtocol, FileProtocol->Open);
|
||||
|
||||
sleep(3);
|
||||
@@ -299,7 +126,7 @@ STATIC EFI_STATUS EFIAPI ventoy_open_protocol
|
||||
IN UINT32 Attributes
|
||||
)
|
||||
{
|
||||
debug("ventoy_open_protocol:%a", ventoy_get_guid_name(Protocol));
|
||||
debug("ventoy_open_protocol:<%p> %a", Handle, ventoy_get_guid_name(Protocol)); debug_sleep();
|
||||
return g_system_wrapper.OriOpenProtocol(Handle, Protocol, Interface, AgentHandle, ControllerHandle, Attributes);
|
||||
}
|
||||
|
||||
@@ -310,15 +137,91 @@ STATIC EFI_STATUS EFIAPI ventoy_locate_protocol
|
||||
OUT VOID **Interface
|
||||
)
|
||||
{
|
||||
debug("ventoy_locate_protocol:%a", ventoy_get_guid_name(Protocol));
|
||||
debug("ventoy_locate_protocol:%a", ventoy_get_guid_name(Protocol)); debug_sleep();
|
||||
return g_system_wrapper.OriLocateProtocol(Protocol, Registration, Interface);
|
||||
}
|
||||
|
||||
STATIC EFI_STATUS EFIAPI ventoy_locate_handle_buffer
|
||||
(
|
||||
IN EFI_LOCATE_SEARCH_TYPE SearchType,
|
||||
IN EFI_GUID *Protocol, OPTIONAL
|
||||
IN VOID *SearchKey, OPTIONAL
|
||||
IN OUT UINTN *NoHandles,
|
||||
OUT EFI_HANDLE **Buffer
|
||||
)
|
||||
{
|
||||
debug("ventoy_locate_handle_buffer:%a", ventoy_get_guid_name(Protocol)); debug_sleep();
|
||||
return g_system_wrapper.OriLocateHandleBuffer(SearchType, Protocol, SearchKey, NoHandles, Buffer);
|
||||
}
|
||||
|
||||
STATIC EFI_STATUS EFIAPI ventoy_protocol_per_handle
|
||||
(
|
||||
IN EFI_HANDLE Handle,
|
||||
OUT EFI_GUID ***ProtocolBuffer,
|
||||
OUT UINTN *ProtocolBufferCount
|
||||
)
|
||||
{
|
||||
debug("ventoy_protocol_per_handle:%p", Handle); debug_sleep();
|
||||
return g_system_wrapper.OriProtocolsPerHandle(Handle, ProtocolBuffer, ProtocolBufferCount);
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_locate_handle
|
||||
(
|
||||
IN EFI_LOCATE_SEARCH_TYPE SearchType,
|
||||
IN EFI_GUID *Protocol, OPTIONAL
|
||||
IN VOID *SearchKey, OPTIONAL
|
||||
IN OUT UINTN *BufferSize,
|
||||
OUT EFI_HANDLE *Buffer
|
||||
)
|
||||
{
|
||||
UINTN i;
|
||||
EFI_HANDLE Handle;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
|
||||
debug("ventoy_locate_handle: %d %a %p", SearchType, ventoy_get_guid_name(Protocol), SearchKey);
|
||||
Status = g_system_wrapper.OriLocateHandle(SearchType, Protocol, SearchKey, BufferSize, Buffer);
|
||||
debug("ventoy_locate_handle: %r Handle Count:%u", Status, *BufferSize/sizeof(EFI_HANDLE));
|
||||
|
||||
if (EFI_SUCCESS == Status)
|
||||
{
|
||||
for (i = 0; i < *BufferSize / sizeof(EFI_HANDLE); i++)
|
||||
{
|
||||
if (Buffer[i] == gBlockData.Handle)
|
||||
{
|
||||
Handle = Buffer[0];
|
||||
Buffer[0] = Buffer[i];
|
||||
Buffer[i] = Handle;
|
||||
debug("####### Handle at %u", i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
debug_sleep();
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
STATIC EFI_STATUS EFIAPI ventoy_locate_device_path
|
||||
(
|
||||
IN EFI_GUID *Protocol,
|
||||
IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,
|
||||
OUT EFI_HANDLE *Device
|
||||
)
|
||||
{
|
||||
debug("ventoy_locate_device_path:%a", ventoy_get_guid_name(Protocol)); debug_sleep();
|
||||
return g_system_wrapper.OriLocateDevicePath(Protocol, DevicePath, Device);
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_wrapper_system(VOID)
|
||||
{
|
||||
ventoy_wrapper(gBS, g_system_wrapper, LocateProtocol, ventoy_locate_protocol);
|
||||
ventoy_wrapper(gBS, g_system_wrapper, HandleProtocol, ventoy_handle_protocol);
|
||||
ventoy_wrapper(gBS, g_system_wrapper, OpenProtocol, ventoy_open_protocol);
|
||||
ventoy_wrapper(gBS, g_system_wrapper, LocateProtocol, ventoy_locate_protocol);
|
||||
ventoy_wrapper(gBS, g_system_wrapper, HandleProtocol, ventoy_handle_protocol);
|
||||
ventoy_wrapper(gBS, g_system_wrapper, OpenProtocol, ventoy_open_protocol);
|
||||
ventoy_wrapper(gBS, g_system_wrapper, LocateHandleBuffer, ventoy_locate_handle_buffer);
|
||||
ventoy_wrapper(gBS, g_system_wrapper, ProtocolsPerHandle, ventoy_protocol_per_handle);
|
||||
ventoy_wrapper(gBS, g_system_wrapper, LocateHandle, ventoy_locate_handle);
|
||||
ventoy_wrapper(gBS, g_system_wrapper, LocateDevicePath, ventoy_locate_device_path);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
@@ -0,0 +1,179 @@
|
||||
/******************************************************************************
|
||||
* Memhole.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 <Uefi.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/PrintLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DevicePathLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||
#include <Library/UefiApplicationEntryPoint.h>
|
||||
#include <Protocol/LoadedImage.h>
|
||||
#include <Guid/FileInfo.h>
|
||||
#include <Guid/FileSystemInfo.h>
|
||||
#include <Protocol/BlockIo.h>
|
||||
#include <Protocol/RamDisk.h>
|
||||
#include <Protocol/SimpleFileSystem.h>
|
||||
#include <VtoyUtil.h>
|
||||
|
||||
STATIC BOOLEAN IsMemContiguous
|
||||
(
|
||||
IN CONST EFI_MEMORY_DESCRIPTOR *Prev,
|
||||
IN CONST EFI_MEMORY_DESCRIPTOR *Curr,
|
||||
IN CONST EFI_MEMORY_DESCRIPTOR *Next
|
||||
)
|
||||
{
|
||||
UINTN Addr1 = 0;
|
||||
UINTN Addr2 = 0;
|
||||
|
||||
if (Prev == NULL || Curr == NULL || Next == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (Prev->Type == EfiBootServicesData &&
|
||||
Curr->Type == EfiConventionalMemory &&
|
||||
Next->Type == EfiBootServicesData)
|
||||
{
|
||||
Addr1 = Prev->PhysicalStart + MultU64x64(SIZE_4KB, Prev->NumberOfPages);
|
||||
Addr2 = Curr->PhysicalStart + MultU64x64(SIZE_4KB, Curr->NumberOfPages);
|
||||
|
||||
if (Addr1 == Curr->PhysicalStart && Addr2 == Next->PhysicalStart)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
STATIC EFI_MEMORY_DESCRIPTOR* GetMemDesc
|
||||
(
|
||||
OUT UINTN *pSize,
|
||||
OUT UINTN *pItemSize,
|
||||
OUT UINTN *pDescCount
|
||||
)
|
||||
{
|
||||
UINTN Size = 0;
|
||||
UINTN MapKey = 0;
|
||||
UINTN ItemSize = 0;
|
||||
UINTN DescCount = 0;
|
||||
UINT32 Version = 0;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_MEMORY_DESCRIPTOR *pDesc = NULL;
|
||||
EFI_MEMORY_DESCRIPTOR *Curr = NULL;
|
||||
|
||||
Status = gBS->GetMemoryMap(&Size, pDesc, &MapKey, &ItemSize, &Version);
|
||||
if (EFI_BUFFER_TOO_SMALL != Status)
|
||||
{
|
||||
debug("GetMemoryMap: %r", Status);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Size += SIZE_1KB;
|
||||
pDesc = AllocatePool(Size);
|
||||
if (!pDesc)
|
||||
{
|
||||
debug("AllocatePool: %lu failed", Size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ZeroMem(pDesc, Size);
|
||||
|
||||
Status = gBS->GetMemoryMap(&Size, pDesc, &MapKey, &ItemSize, &Version);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
debug("GetMemoryMap: %r", Status);
|
||||
FreePool(pDesc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Curr = pDesc;
|
||||
while (Curr && Curr < (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)pDesc + Size))
|
||||
{
|
||||
DescCount++;
|
||||
Curr = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)Curr + ItemSize);
|
||||
}
|
||||
|
||||
*pSize = Size;
|
||||
*pItemSize = ItemSize;
|
||||
*pDescCount = DescCount;
|
||||
|
||||
debug("GetMemoryMap: ItemSize:%lu Count:%lu", ItemSize, DescCount);
|
||||
|
||||
return pDesc;
|
||||
}
|
||||
|
||||
EFI_STATUS FixWindowsMemhole(IN EFI_HANDLE ImageHandle, IN CONST CHAR16 *CmdLine)
|
||||
{
|
||||
UINTN Size = 0;
|
||||
UINTN ItemSize = 0;
|
||||
UINTN DescCount = 0;
|
||||
UINTN TotalMem = 0;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_PHYSICAL_ADDRESS AllocAddr = 0;
|
||||
EFI_MEMORY_DESCRIPTOR *pDescs = NULL;
|
||||
EFI_MEMORY_DESCRIPTOR *Prev = NULL;
|
||||
EFI_MEMORY_DESCRIPTOR *Next = NULL;
|
||||
EFI_MEMORY_DESCRIPTOR *Curr = NULL;
|
||||
|
||||
(VOID)ImageHandle;
|
||||
(VOID)CmdLine;
|
||||
|
||||
pDescs = GetMemDesc(&Size, &ItemSize, &DescCount);
|
||||
if (!pDescs)
|
||||
{
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (DescCount < 500)
|
||||
{
|
||||
FreePool(pDescs);
|
||||
Printf("There is no need to fixup (%lu)\n", DescCount);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
Curr = pDescs;
|
||||
while ((UINT8 *)Curr < (UINT8 *)pDescs + Size)
|
||||
{
|
||||
Next = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)Curr + ItemSize);
|
||||
|
||||
if (IsMemContiguous(Prev, Curr, Next))
|
||||
{
|
||||
AllocAddr = Curr->PhysicalStart;
|
||||
Status = gBS->AllocatePages(AllocateAddress, EfiBootServicesData, Curr->NumberOfPages, &AllocAddr);
|
||||
if (EFI_SUCCESS == Status)
|
||||
{
|
||||
TotalMem += MultU64x64(SIZE_4KB, Curr->NumberOfPages);
|
||||
}
|
||||
}
|
||||
|
||||
Prev = Curr;
|
||||
Curr = Next;
|
||||
}
|
||||
|
||||
Printf("Fixup Windows mmap issue OK (%lu)\n", TotalMem);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
@@ -0,0 +1,135 @@
|
||||
/******************************************************************************
|
||||
* VtoyUtil.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 <Uefi.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/PrintLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DevicePathLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||
#include <Library/UefiApplicationEntryPoint.h>
|
||||
#include <Protocol/LoadedImage.h>
|
||||
#include <Guid/FileInfo.h>
|
||||
#include <Guid/FileSystemInfo.h>
|
||||
#include <Protocol/BlockIo.h>
|
||||
#include <Protocol/RamDisk.h>
|
||||
#include <Protocol/SimpleFileSystem.h>
|
||||
#include <VtoyUtil.h>
|
||||
|
||||
BOOLEAN gVtoyDebugPrint = FALSE;
|
||||
STATIC CONST CHAR16 *gCurFeature= NULL;
|
||||
STATIC CHAR16 *gCmdLine = NULL;
|
||||
STATIC grub_env_printf_pf g_env_printf = NULL;
|
||||
|
||||
STATIC VtoyUtilFeature gFeatureList[] =
|
||||
{
|
||||
{ L"fix_windows_mmap", FixWindowsMemhole },
|
||||
};
|
||||
|
||||
VOID EFIAPI VtoyUtilDebug(IN CONST CHAR8 *Format, ...)
|
||||
{
|
||||
VA_LIST Marker;
|
||||
CHAR8 Buffer[512];
|
||||
|
||||
VA_START (Marker, Format);
|
||||
AsciiVSPrint(Buffer, sizeof(Buffer), Format, Marker);
|
||||
VA_END (Marker);
|
||||
|
||||
if (g_env_printf)
|
||||
{
|
||||
g_env_printf("%s", Buffer);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC EFI_STATUS ParseCmdline(IN EFI_HANDLE ImageHandle)
|
||||
{
|
||||
CHAR16 *pPos = NULL;
|
||||
CHAR16 *pCmdLine = NULL;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
ventoy_grub_param *pGrubParam = NULL;
|
||||
EFI_LOADED_IMAGE_PROTOCOL *pImageInfo = NULL;
|
||||
|
||||
Status = gBS->HandleProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&pImageInfo);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
pCmdLine = (CHAR16 *)AllocatePool(pImageInfo->LoadOptionsSize + 4);
|
||||
SetMem(pCmdLine, pImageInfo->LoadOptionsSize + 4, 0);
|
||||
CopyMem(pCmdLine, pImageInfo->LoadOptions, pImageInfo->LoadOptionsSize);
|
||||
|
||||
if (StrStr(pCmdLine, L"debug"))
|
||||
{
|
||||
gVtoyDebugPrint = TRUE;
|
||||
}
|
||||
|
||||
pPos = StrStr(pCmdLine, L"env_param=");
|
||||
if (!pPos)
|
||||
{
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
pGrubParam = (ventoy_grub_param *)StrHexToUintn(pPos + StrLen(L"env_param="));
|
||||
g_env_printf = pGrubParam->grub_env_printf;
|
||||
|
||||
pPos = StrStr(pCmdLine, L"feature=");
|
||||
if (!pPos)
|
||||
{
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
gCurFeature = pPos + StrLen(L"feature=");
|
||||
|
||||
gCmdLine = pCmdLine;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI VtoyUtilEfiMain
|
||||
(
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
UINTN i;
|
||||
UINTN Len;
|
||||
|
||||
ParseCmdline(ImageHandle);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(gFeatureList); i++)
|
||||
{
|
||||
Len = StrLen(gFeatureList[i].Cmd);
|
||||
if (StrnCmp(gFeatureList[i].Cmd, gCurFeature, Len) == 0)
|
||||
{
|
||||
debug("Find main proc <%s>", gFeatureList[i].Cmd);
|
||||
gFeatureList[i].MainProc(ImageHandle, gCurFeature + Len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FreePool(gCmdLine);
|
||||
gCmdLine = NULL;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
@@ -0,0 +1,63 @@
|
||||
/******************************************************************************
|
||||
* VtoyUtil.h
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __VTOYUTIL_H__
|
||||
#define __VTOYUTIL_H__
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
typedef EFI_STATUS (*VTOY_UTIL_PROC_PF)(IN EFI_HANDLE ImageHandle, IN CONST CHAR16 *CmdLine);
|
||||
typedef int (*grub_env_set_pf)(const char *name, const char *val);
|
||||
typedef const char * (*grub_env_get_pf)(const char *name);
|
||||
typedef int (*grub_env_printf_pf)(const char *fmt, ...);
|
||||
|
||||
typedef struct ventoy_grub_param_file_replace
|
||||
{
|
||||
UINT32 magic;
|
||||
char old_file_name[4][256];
|
||||
UINT32 old_file_cnt;
|
||||
UINT32 new_file_virtual_id;
|
||||
}ventoy_grub_param_file_replace;
|
||||
|
||||
typedef struct ventoy_grub_param
|
||||
{
|
||||
grub_env_get_pf grub_env_get;
|
||||
grub_env_set_pf grub_env_set;
|
||||
ventoy_grub_param_file_replace file_replace;
|
||||
grub_env_printf_pf grub_env_printf;
|
||||
}ventoy_grub_param;
|
||||
#pragma pack()
|
||||
|
||||
|
||||
typedef struct VtoyUtilFeature
|
||||
{
|
||||
CONST CHAR16 *Cmd;
|
||||
VTOY_UTIL_PROC_PF MainProc;
|
||||
}VtoyUtilFeature;
|
||||
|
||||
extern BOOLEAN gVtoyDebugPrint;
|
||||
VOID EFIAPI VtoyUtilDebug(IN CONST CHAR8 *Format, ...);
|
||||
#define debug(expr, ...) if (gVtoyDebugPrint) VtoyUtilDebug("[VTOY] "expr"\n", ##__VA_ARGS__)
|
||||
#define Printf VtoyUtilDebug
|
||||
|
||||
EFI_STATUS FixWindowsMemhole(IN EFI_HANDLE ImageHandle, IN CONST CHAR16 *CmdLine);
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,80 @@
|
||||
#************************************************************************************
|
||||
# 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/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = VtoyUtil
|
||||
FILE_GUID = a43466a0-68c6-469d-ba4b-678bbe90bc47
|
||||
MODULE_TYPE = UEFI_APPLICATION
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = VtoyUtilEfiMain
|
||||
|
||||
|
||||
[Sources]
|
||||
VtoyUtil.h
|
||||
VtoyUtil.c
|
||||
Memhole.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
ShellPkg/ShellPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
UefiApplicationEntryPoint
|
||||
UefiLib
|
||||
DebugLib
|
||||
|
||||
[Guids]
|
||||
gShellVariableGuid
|
||||
gEfiVirtualCdGuid
|
||||
gEfiFileInfoGuid
|
||||
|
||||
[Protocols]
|
||||
gEfiLoadedImageProtocolGuid
|
||||
gEfiBlockIoProtocolGuid
|
||||
gEfiDevicePathProtocolGuid
|
||||
gEfiSimpleFileSystemProtocolGuid
|
||||
gEfiRamDiskProtocolGuid
|
||||
gEfiAbsolutePointerProtocolGuid
|
||||
gEfiAcpiTableProtocolGuid
|
||||
gEfiBlockIo2ProtocolGuid
|
||||
gEfiBusSpecificDriverOverrideProtocolGuid
|
||||
gEfiComponentNameProtocolGuid
|
||||
gEfiComponentName2ProtocolGuid
|
||||
gEfiDriverBindingProtocolGuid
|
||||
gEfiDiskIoProtocolGuid
|
||||
gEfiDiskIo2ProtocolGuid
|
||||
gEfiGraphicsOutputProtocolGuid
|
||||
gEfiHiiConfigAccessProtocolGuid
|
||||
gEfiHiiFontProtocolGuid
|
||||
gEfiLoadFileProtocolGuid
|
||||
gEfiLoadFile2ProtocolGuid
|
||||
gEfiLoadedImageProtocolGuid
|
||||
gEfiLoadedImageDevicePathProtocolGuid
|
||||
gEfiPciIoProtocolGuid
|
||||
gEfiSerialIoProtocolGuid
|
||||
gEfiSimpleTextInProtocolGuid
|
||||
gEfiSimpleTextInputExProtocolGuid
|
||||
gEfiSimpleTextOutProtocolGuid
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -204,6 +204,7 @@
|
||||
|
||||
[Components]
|
||||
MdeModulePkg/Application/Ventoy/Ventoy.inf
|
||||
MdeModulePkg/Application/VtoyUtil/VtoyUtil.inf
|
||||
MdeModulePkg/Application/HelloWorld/HelloWorld.inf
|
||||
MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.inf
|
||||
MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf
|
||||
|
1
EfiISO/ISO/EFI/BOOT/BOOTX64.EFI
Normal file
@@ -0,0 +1 @@
|
||||
1
|
13
EfiISO/mkefiiso.sh
Normal file
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
rm -f ventoy_efiboot.img.*
|
||||
|
||||
cd ISO
|
||||
mkisofs -R -D -sysid VENTOY -V VENTOY -P "longpanda admin@ventoy.net" -p 'https://www.ventoy.net' -o ../ventoy_efiboot.img ./
|
||||
cd ..
|
||||
|
||||
xz --check=crc32 ventoy_efiboot.img
|
||||
|
||||
rm -f ../INSTALL/ventoy/ventoy_efiboot.img.xz
|
||||
cp -a ventoy_efiboot.img.xz ../INSTALL/ventoy/
|
||||
|
@@ -114,11 +114,12 @@ static int ventoy_iso_open(const char *path, struct fuse_file_info *file)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ventoy_read_iso_sector(uint32_t sector, uint32_t num, void *buf)
|
||||
static int ventoy_read_iso_sector(uint32_t sector, uint32_t num, char *buf)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint32_t leftSec = 0;
|
||||
uint32_t readSec = 0;
|
||||
off_t offset = 0;
|
||||
dmtable_entry *entry = NULL;
|
||||
|
||||
for (i = 0; i < g_disk_entry_num && num > 0; i++)
|
||||
@@ -127,14 +128,15 @@ static int ventoy_read_iso_sector(uint32_t sector, uint32_t num, void *buf)
|
||||
|
||||
if (sector >= entry->isoSector && sector < entry->isoSector + entry->sectorNum)
|
||||
{
|
||||
lseek(g_disk_fd, (entry->diskSector + (sector - entry->isoSector)) * 512, SEEK_SET);
|
||||
offset = (entry->diskSector + (sector - entry->isoSector)) * 512;
|
||||
|
||||
leftSec = entry->sectorNum - (sector - entry->isoSector);
|
||||
readSec = (leftSec > num) ? num : leftSec;
|
||||
|
||||
read(g_disk_fd, buf, readSec * 512);
|
||||
pread(g_disk_fd, buf, readSec * 512, offset);
|
||||
|
||||
sector += readSec;
|
||||
buf += readSec * 512;
|
||||
num -= readSec;
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
};
|
||||
|
||||
@@ -1578,10 +1589,13 @@ module = {
|
||||
name = ventoy;
|
||||
common = ventoy/ventoy.c;
|
||||
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;
|
||||
common = ventoy/xpress.c;
|
||||
common = ventoy/huffman.c;
|
||||
};
|
||||
|
||||
|
1111
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/blscfg.c
Normal file
894
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/legacycfg.c
Normal file
@@ -0,0 +1,894 @@
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2000, 2001, 2010 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/types.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/script_sh.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/legacy_parse.h>
|
||||
#include <grub/crypto.h>
|
||||
#include <grub/auth.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/partition.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
/* Helper for legacy_file. */
|
||||
static grub_err_t
|
||||
legacy_file_getline (char **line, int cont __attribute__ ((unused)),
|
||||
void *data __attribute__ ((unused)))
|
||||
{
|
||||
*line = 0;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
legacy_file (const char *filename)
|
||||
{
|
||||
grub_file_t file;
|
||||
char *entryname = NULL, *entrysrc = NULL;
|
||||
grub_menu_t menu;
|
||||
char *suffix = grub_strdup ("");
|
||||
|
||||
if (!suffix)
|
||||
return grub_errno;
|
||||
|
||||
file = grub_file_open (filename, GRUB_FILE_TYPE_CONFIG);
|
||||
if (! file)
|
||||
{
|
||||
grub_free (suffix);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
menu = grub_env_get_menu ();
|
||||
if (! menu)
|
||||
{
|
||||
menu = grub_zalloc (sizeof (*menu));
|
||||
if (! menu)
|
||||
{
|
||||
grub_free (suffix);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
grub_env_set_menu (menu);
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
char *buf = grub_file_getline (file);
|
||||
char *parsed = NULL;
|
||||
|
||||
if (!buf && grub_errno)
|
||||
{
|
||||
grub_file_close (file);
|
||||
grub_free (suffix);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
if (!buf)
|
||||
break;
|
||||
|
||||
{
|
||||
char *oldname = NULL;
|
||||
char *newsuffix;
|
||||
char *ptr;
|
||||
|
||||
for (ptr = buf; *ptr && grub_isspace (*ptr); ptr++);
|
||||
|
||||
oldname = entryname;
|
||||
parsed = grub_legacy_parse (ptr, &entryname, &newsuffix);
|
||||
grub_free (buf);
|
||||
buf = NULL;
|
||||
if (newsuffix)
|
||||
{
|
||||
char *t;
|
||||
|
||||
t = suffix;
|
||||
suffix = grub_realloc (suffix, grub_strlen (suffix)
|
||||
+ grub_strlen (newsuffix) + 1);
|
||||
if (!suffix)
|
||||
{
|
||||
grub_free (t);
|
||||
grub_free (entrysrc);
|
||||
grub_free (parsed);
|
||||
grub_free (newsuffix);
|
||||
grub_free (suffix);
|
||||
return grub_errno;
|
||||
}
|
||||
grub_memcpy (suffix + grub_strlen (suffix), newsuffix,
|
||||
grub_strlen (newsuffix) + 1);
|
||||
grub_free (newsuffix);
|
||||
newsuffix = NULL;
|
||||
}
|
||||
if (oldname != entryname && oldname)
|
||||
{
|
||||
const char **args = grub_malloc (sizeof (args[0]));
|
||||
if (!args)
|
||||
{
|
||||
grub_file_close (file);
|
||||
return grub_errno;
|
||||
}
|
||||
args[0] = oldname;
|
||||
grub_normal_add_menu_entry (1, args, NULL, NULL, "legacy",
|
||||
NULL, NULL,
|
||||
entrysrc, 0, NULL, NULL);
|
||||
grub_free (args);
|
||||
entrysrc[0] = 0;
|
||||
grub_free (oldname);
|
||||
}
|
||||
}
|
||||
|
||||
if (parsed && !entryname)
|
||||
{
|
||||
grub_normal_parse_line (parsed, legacy_file_getline, NULL);
|
||||
grub_print_error ();
|
||||
grub_free (parsed);
|
||||
parsed = NULL;
|
||||
}
|
||||
else if (parsed)
|
||||
{
|
||||
if (!entrysrc)
|
||||
entrysrc = parsed;
|
||||
else
|
||||
{
|
||||
char *t;
|
||||
|
||||
t = entrysrc;
|
||||
entrysrc = grub_realloc (entrysrc, grub_strlen (entrysrc)
|
||||
+ grub_strlen (parsed) + 1);
|
||||
if (!entrysrc)
|
||||
{
|
||||
grub_free (t);
|
||||
grub_free (parsed);
|
||||
grub_free (suffix);
|
||||
return grub_errno;
|
||||
}
|
||||
grub_memcpy (entrysrc + grub_strlen (entrysrc), parsed,
|
||||
grub_strlen (parsed) + 1);
|
||||
grub_free (parsed);
|
||||
parsed = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
grub_file_close (file);
|
||||
|
||||
if (entryname)
|
||||
{
|
||||
const char **args = grub_malloc (sizeof (args[0]));
|
||||
if (!args)
|
||||
{
|
||||
grub_file_close (file);
|
||||
grub_free (suffix);
|
||||
grub_free (entrysrc);
|
||||
return grub_errno;
|
||||
}
|
||||
args[0] = entryname;
|
||||
grub_normal_add_menu_entry (1, args, NULL, NULL, NULL,
|
||||
NULL, NULL, entrysrc, 0, NULL,
|
||||
NULL);
|
||||
grub_free (args);
|
||||
}
|
||||
|
||||
grub_normal_parse_line (suffix, legacy_file_getline, NULL);
|
||||
grub_print_error ();
|
||||
grub_free (suffix);
|
||||
grub_free (entrysrc);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_legacy_source (struct grub_command *cmd,
|
||||
int argc, char **args)
|
||||
{
|
||||
int new_env, extractor;
|
||||
grub_err_t ret;
|
||||
|
||||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
||||
|
||||
extractor = (cmd->name[0] == 'e');
|
||||
new_env = (cmd->name[extractor ? (sizeof ("extract_legacy_entries_") - 1)
|
||||
: (sizeof ("legacy_") - 1)] == 'c');
|
||||
|
||||
if (new_env)
|
||||
grub_cls ();
|
||||
|
||||
if (new_env && !extractor)
|
||||
grub_env_context_open ();
|
||||
if (extractor)
|
||||
grub_env_extractor_open (!new_env);
|
||||
|
||||
ret = legacy_file (args[0]);
|
||||
|
||||
if (new_env)
|
||||
{
|
||||
grub_menu_t menu;
|
||||
menu = grub_env_get_menu ();
|
||||
if (menu && menu->size)
|
||||
grub_show_menu (menu, 1, 0);
|
||||
if (!extractor)
|
||||
grub_env_context_close ();
|
||||
}
|
||||
if (extractor)
|
||||
grub_env_extractor_close (!new_env);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static enum
|
||||
{
|
||||
GUESS_IT, LINUX, MULTIBOOT, KFREEBSD, KNETBSD, KOPENBSD
|
||||
} kernel_type;
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
int i;
|
||||
#ifdef TODO
|
||||
int no_mem_option = 0;
|
||||
#endif
|
||||
struct grub_command *cmd;
|
||||
char **cutargs;
|
||||
int cutargc;
|
||||
grub_err_t err = GRUB_ERR_NONE;
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
/* FIXME: really support this. */
|
||||
if (argc >= 1 && grub_strcmp (args[0], "--no-mem-option") == 0)
|
||||
{
|
||||
#ifdef TODO
|
||||
no_mem_option = 1;
|
||||
#endif
|
||||
argc--;
|
||||
args++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* linux16 handles both zImages and bzImages. */
|
||||
if (argc >= 1 && (grub_strcmp (args[0], "--type=linux") == 0
|
||||
|| grub_strcmp (args[0], "--type=biglinux") == 0))
|
||||
{
|
||||
kernel_type = LINUX;
|
||||
argc--;
|
||||
args++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argc >= 1 && grub_strcmp (args[0], "--type=multiboot") == 0)
|
||||
{
|
||||
kernel_type = MULTIBOOT;
|
||||
argc--;
|
||||
args++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argc >= 1 && grub_strcmp (args[0], "--type=freebsd") == 0)
|
||||
{
|
||||
kernel_type = KFREEBSD;
|
||||
argc--;
|
||||
args++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argc >= 1 && grub_strcmp (args[0], "--type=openbsd") == 0)
|
||||
{
|
||||
kernel_type = KOPENBSD;
|
||||
argc--;
|
||||
args++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argc >= 1 && grub_strcmp (args[0], "--type=netbsd") == 0)
|
||||
{
|
||||
kernel_type = KNETBSD;
|
||||
argc--;
|
||||
args++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc < 2)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
||||
|
||||
cutargs = grub_malloc (sizeof (cutargs[0]) * (argc - 1));
|
||||
if (!cutargs)
|
||||
return grub_errno;
|
||||
cutargc = argc - 1;
|
||||
grub_memcpy (cutargs + 1, args + 2, sizeof (cutargs[0]) * (argc - 2));
|
||||
cutargs[0] = args[0];
|
||||
|
||||
do
|
||||
{
|
||||
/* First try Linux. */
|
||||
if (kernel_type == GUESS_IT || kernel_type == LINUX)
|
||||
{
|
||||
#ifdef GRUB_MACHINE_PCBIOS
|
||||
cmd = grub_command_find ("linux16");
|
||||
#else
|
||||
cmd = grub_command_find ("linux");
|
||||
#endif
|
||||
if (cmd)
|
||||
{
|
||||
if (!(cmd->func) (cmd, cutargc, cutargs))
|
||||
{
|
||||
kernel_type = LINUX;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
/* Then multiboot. */
|
||||
if (kernel_type == GUESS_IT || kernel_type == MULTIBOOT)
|
||||
{
|
||||
cmd = grub_command_find ("multiboot");
|
||||
if (cmd)
|
||||
{
|
||||
if (!(cmd->func) (cmd, argc, args))
|
||||
{
|
||||
kernel_type = MULTIBOOT;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
{
|
||||
int bsd_device = -1;
|
||||
int bsd_slice = -1;
|
||||
int bsd_part = -1;
|
||||
{
|
||||
grub_device_t dev;
|
||||
const char *hdbiasstr;
|
||||
int hdbias = 0;
|
||||
hdbiasstr = grub_env_get ("legacy_hdbias");
|
||||
if (hdbiasstr)
|
||||
{
|
||||
hdbias = grub_strtoul (hdbiasstr, 0, 0);
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
dev = grub_device_open (0);
|
||||
if (dev && dev->disk
|
||||
&& dev->disk->dev->id == GRUB_DISK_DEVICE_BIOSDISK_ID
|
||||
&& dev->disk->id >= 0x80 && dev->disk->id <= 0x90)
|
||||
{
|
||||
struct grub_partition *part = dev->disk->partition;
|
||||
bsd_device = dev->disk->id - 0x80 - hdbias;
|
||||
if (part && (grub_strcmp (part->partmap->name, "netbsd") == 0
|
||||
|| grub_strcmp (part->partmap->name, "openbsd") == 0
|
||||
|| grub_strcmp (part->partmap->name, "bsd") == 0))
|
||||
{
|
||||
bsd_part = part->number;
|
||||
part = part->parent;
|
||||
}
|
||||
if (part && grub_strcmp (part->partmap->name, "msdos") == 0)
|
||||
bsd_slice = part->number;
|
||||
}
|
||||
if (dev)
|
||||
grub_device_close (dev);
|
||||
}
|
||||
|
||||
/* k*BSD didn't really work well with grub-legacy. */
|
||||
if (kernel_type == GUESS_IT || kernel_type == KFREEBSD)
|
||||
{
|
||||
char buf[sizeof("adXXXXXXXXXXXXsXXXXXXXXXXXXYYY")];
|
||||
if (bsd_device != -1)
|
||||
{
|
||||
if (bsd_slice != -1 && bsd_part != -1)
|
||||
grub_snprintf(buf, sizeof(buf), "ad%ds%d%c", bsd_device,
|
||||
bsd_slice, 'a' + bsd_part);
|
||||
else if (bsd_slice != -1)
|
||||
grub_snprintf(buf, sizeof(buf), "ad%ds%d", bsd_device,
|
||||
bsd_slice);
|
||||
else
|
||||
grub_snprintf(buf, sizeof(buf), "ad%d", bsd_device);
|
||||
grub_env_set ("kFreeBSD.vfs.root.mountfrom", buf);
|
||||
}
|
||||
else
|
||||
grub_env_unset ("kFreeBSD.vfs.root.mountfrom");
|
||||
cmd = grub_command_find ("kfreebsd");
|
||||
if (cmd)
|
||||
{
|
||||
if (!(cmd->func) (cmd, cutargc, cutargs))
|
||||
{
|
||||
kernel_type = KFREEBSD;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
{
|
||||
char **bsdargs;
|
||||
int bsdargc;
|
||||
char bsddevname[sizeof ("wdXXXXXXXXXXXXY")];
|
||||
int found = 0;
|
||||
|
||||
if (bsd_device == -1)
|
||||
{
|
||||
bsdargs = cutargs;
|
||||
bsdargc = cutargc;
|
||||
}
|
||||
else
|
||||
{
|
||||
char rbuf[3] = "-r";
|
||||
bsdargc = cutargc + 2;
|
||||
bsdargs = grub_malloc (sizeof (bsdargs[0]) * bsdargc);
|
||||
if (!bsdargs)
|
||||
{
|
||||
err = grub_errno;
|
||||
goto out;
|
||||
}
|
||||
grub_memcpy (bsdargs, args, argc * sizeof (bsdargs[0]));
|
||||
bsdargs[argc] = rbuf;
|
||||
bsdargs[argc + 1] = bsddevname;
|
||||
grub_snprintf (bsddevname, sizeof (bsddevname),
|
||||
"wd%d%c", bsd_device,
|
||||
bsd_part != -1 ? bsd_part + 'a' : 'c');
|
||||
}
|
||||
if (kernel_type == GUESS_IT || kernel_type == KNETBSD)
|
||||
{
|
||||
cmd = grub_command_find ("knetbsd");
|
||||
if (cmd)
|
||||
{
|
||||
if (!(cmd->func) (cmd, bsdargc, bsdargs))
|
||||
{
|
||||
kernel_type = KNETBSD;
|
||||
found = 1;
|
||||
goto free_bsdargs;
|
||||
}
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
if (kernel_type == GUESS_IT || kernel_type == KOPENBSD)
|
||||
{
|
||||
cmd = grub_command_find ("kopenbsd");
|
||||
if (cmd)
|
||||
{
|
||||
if (!(cmd->func) (cmd, bsdargc, bsdargs))
|
||||
{
|
||||
kernel_type = KOPENBSD;
|
||||
found = 1;
|
||||
goto free_bsdargs;
|
||||
}
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
free_bsdargs:
|
||||
if (bsdargs != cutargs)
|
||||
grub_free (bsdargs);
|
||||
if (found)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (0);
|
||||
|
||||
err = grub_error (GRUB_ERR_BAD_OS, "couldn't load file %s",
|
||||
args[0]);
|
||||
out:
|
||||
grub_free (cutargs);
|
||||
return err;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_legacy_initrd (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
struct grub_command *cmd;
|
||||
|
||||
if (kernel_type == LINUX)
|
||||
{
|
||||
#ifdef GRUB_MACHINE_PCBIOS
|
||||
cmd = grub_command_find ("initrd16");
|
||||
#else
|
||||
cmd = grub_command_find ("initrd");
|
||||
#endif
|
||||
if (!cmd)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"),
|
||||
#ifdef GRUB_MACHINE_PCBIOS
|
||||
"initrd16"
|
||||
#else
|
||||
"initrd"
|
||||
#endif
|
||||
);
|
||||
|
||||
return cmd->func (cmd, argc ? 1 : 0, args);
|
||||
}
|
||||
if (kernel_type == MULTIBOOT)
|
||||
{
|
||||
cmd = grub_command_find ("module");
|
||||
if (!cmd)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"),
|
||||
"module");
|
||||
|
||||
return cmd->func (cmd, argc, args);
|
||||
}
|
||||
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
N_("you need to load the kernel first"));
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_legacy_initrdnounzip (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
struct grub_command *cmd;
|
||||
|
||||
if (kernel_type == LINUX)
|
||||
{
|
||||
cmd = grub_command_find ("initrd16");
|
||||
if (!cmd)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"),
|
||||
"initrd16");
|
||||
|
||||
return cmd->func (cmd, argc, args);
|
||||
}
|
||||
if (kernel_type == MULTIBOOT)
|
||||
{
|
||||
char **newargs;
|
||||
grub_err_t err;
|
||||
char nounzipbuf[10] = "--nounzip";
|
||||
|
||||
cmd = grub_command_find ("module");
|
||||
if (!cmd)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"),
|
||||
"module");
|
||||
|
||||
newargs = grub_malloc ((argc + 1) * sizeof (newargs[0]));
|
||||
if (!newargs)
|
||||
return grub_errno;
|
||||
grub_memcpy (newargs + 1, args, argc * sizeof (newargs[0]));
|
||||
newargs[0] = nounzipbuf;
|
||||
|
||||
err = cmd->func (cmd, argc + 1, newargs);
|
||||
grub_free (newargs);
|
||||
return err;
|
||||
}
|
||||
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
N_("you need to load the kernel first"));
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
check_password_deny (const char *user __attribute__ ((unused)),
|
||||
const char *entered __attribute__ ((unused)),
|
||||
void *password __attribute__ ((unused)))
|
||||
{
|
||||
return GRUB_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
#define MD5_HASHLEN 16
|
||||
|
||||
struct legacy_md5_password
|
||||
{
|
||||
grub_uint8_t *salt;
|
||||
int saltlen;
|
||||
grub_uint8_t hash[MD5_HASHLEN];
|
||||
};
|
||||
|
||||
static int
|
||||
check_password_md5_real (const char *entered,
|
||||
struct legacy_md5_password *pw)
|
||||
{
|
||||
grub_size_t enteredlen = grub_strlen (entered);
|
||||
unsigned char alt_result[MD5_HASHLEN];
|
||||
unsigned char *digest;
|
||||
grub_uint8_t *ctx;
|
||||
grub_size_t i;
|
||||
int ret;
|
||||
|
||||
ctx = grub_zalloc (GRUB_MD_MD5->contextsize);
|
||||
if (!ctx)
|
||||
return 0;
|
||||
|
||||
GRUB_MD_MD5->init (ctx);
|
||||
GRUB_MD_MD5->write (ctx, entered, enteredlen);
|
||||
GRUB_MD_MD5->write (ctx, pw->salt + 3, pw->saltlen - 3);
|
||||
GRUB_MD_MD5->write (ctx, entered, enteredlen);
|
||||
digest = GRUB_MD_MD5->read (ctx);
|
||||
GRUB_MD_MD5->final (ctx);
|
||||
grub_memcpy (alt_result, digest, MD5_HASHLEN);
|
||||
|
||||
GRUB_MD_MD5->init (ctx);
|
||||
GRUB_MD_MD5->write (ctx, entered, enteredlen);
|
||||
GRUB_MD_MD5->write (ctx, pw->salt, pw->saltlen); /* include the $1$ header */
|
||||
for (i = enteredlen; i > 16; i -= 16)
|
||||
GRUB_MD_MD5->write (ctx, alt_result, 16);
|
||||
GRUB_MD_MD5->write (ctx, alt_result, i);
|
||||
|
||||
for (i = enteredlen; i > 0; i >>= 1)
|
||||
GRUB_MD_MD5->write (ctx, entered + ((i & 1) ? enteredlen : 0), 1);
|
||||
digest = GRUB_MD_MD5->read (ctx);
|
||||
GRUB_MD_MD5->final (ctx);
|
||||
|
||||
for (i = 0; i < 1000; i++)
|
||||
{
|
||||
grub_memcpy (alt_result, digest, 16);
|
||||
|
||||
GRUB_MD_MD5->init (ctx);
|
||||
if ((i & 1) != 0)
|
||||
GRUB_MD_MD5->write (ctx, entered, enteredlen);
|
||||
else
|
||||
GRUB_MD_MD5->write (ctx, alt_result, 16);
|
||||
|
||||
if (i % 3 != 0)
|
||||
GRUB_MD_MD5->write (ctx, pw->salt + 3, pw->saltlen - 3);
|
||||
|
||||
if (i % 7 != 0)
|
||||
GRUB_MD_MD5->write (ctx, entered, enteredlen);
|
||||
|
||||
if ((i & 1) != 0)
|
||||
GRUB_MD_MD5->write (ctx, alt_result, 16);
|
||||
else
|
||||
GRUB_MD_MD5->write (ctx, entered, enteredlen);
|
||||
digest = GRUB_MD_MD5->read (ctx);
|
||||
GRUB_MD_MD5->final (ctx);
|
||||
}
|
||||
|
||||
ret = (grub_crypto_memcmp (digest, pw->hash, MD5_HASHLEN) == 0);
|
||||
grub_free (ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
check_password_md5 (const char *user,
|
||||
const char *entered,
|
||||
void *password)
|
||||
{
|
||||
if (!check_password_md5_real (entered, password))
|
||||
return GRUB_ACCESS_DENIED;
|
||||
|
||||
grub_auth_authenticate (user);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static inline int
|
||||
ib64t (char c)
|
||||
{
|
||||
if (c == '.')
|
||||
return 0;
|
||||
if (c == '/')
|
||||
return 1;
|
||||
if (c >= '0' && c <= '9')
|
||||
return c - '0' + 2;
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
return c - 'A' + 12;
|
||||
if (c >= 'a' && c <= 'z')
|
||||
return c - 'a' + 38;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static struct legacy_md5_password *
|
||||
parse_legacy_md5 (int argc, char **args)
|
||||
{
|
||||
const char *salt, *saltend;
|
||||
struct legacy_md5_password *pw = NULL;
|
||||
int i;
|
||||
const char *p;
|
||||
|
||||
if (grub_memcmp (args[0], "--md5", sizeof ("--md5")) != 0)
|
||||
goto fail;
|
||||
if (argc == 1)
|
||||
goto fail;
|
||||
if (grub_strlen(args[1]) <= 3)
|
||||
goto fail;
|
||||
salt = args[1];
|
||||
saltend = grub_strchr (salt + 3, '$');
|
||||
if (!saltend)
|
||||
goto fail;
|
||||
pw = grub_malloc (sizeof (*pw));
|
||||
if (!pw)
|
||||
goto fail;
|
||||
|
||||
p = saltend + 1;
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
int n;
|
||||
grub_uint32_t w = 0;
|
||||
|
||||
for (n = 0; n < 4; n++)
|
||||
{
|
||||
int ww = ib64t(*p++);
|
||||
if (ww == -1)
|
||||
goto fail;
|
||||
w |= ww << (n * 6);
|
||||
}
|
||||
pw->hash[i == 4 ? 5 : 12+i] = w & 0xff;
|
||||
pw->hash[6+i] = (w >> 8) & 0xff;
|
||||
pw->hash[i] = (w >> 16) & 0xff;
|
||||
}
|
||||
{
|
||||
int n;
|
||||
grub_uint32_t w = 0;
|
||||
for (n = 0; n < 2; n++)
|
||||
{
|
||||
int ww = ib64t(*p++);
|
||||
if (ww == -1)
|
||||
goto fail;
|
||||
w |= ww << (6 * n);
|
||||
}
|
||||
if (w >= 0x100)
|
||||
goto fail;
|
||||
pw->hash[11] = w;
|
||||
}
|
||||
|
||||
pw->saltlen = saltend - salt;
|
||||
pw->salt = (grub_uint8_t *) grub_strndup (salt, pw->saltlen);
|
||||
if (!pw->salt)
|
||||
goto fail;
|
||||
|
||||
return pw;
|
||||
|
||||
fail:
|
||||
grub_free (pw);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_legacy_password (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
struct legacy_md5_password *pw = NULL;
|
||||
|
||||
if (argc == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
|
||||
if (args[0][0] != '-' || args[0][1] != '-')
|
||||
return grub_normal_set_password ("legacy", args[0]);
|
||||
|
||||
pw = parse_legacy_md5 (argc, args);
|
||||
|
||||
if (pw)
|
||||
return grub_auth_register_authentication ("legacy", check_password_md5, pw);
|
||||
else
|
||||
/* This is to imitate minor difference between grub-legacy in GRUB2.
|
||||
If 2 password commands are executed in a row and second one fails
|
||||
on GRUB2 the password of first one is used, whereas in grub-legacy
|
||||
authenthication is denied. In case of no password command was executed
|
||||
early both versions deny any access. */
|
||||
return grub_auth_register_authentication ("legacy", check_password_deny,
|
||||
NULL);
|
||||
}
|
||||
|
||||
int
|
||||
grub_legacy_check_md5_password (int argc, char **args,
|
||||
char *entered)
|
||||
{
|
||||
struct legacy_md5_password *pw = NULL;
|
||||
int ret;
|
||||
|
||||
if (args[0][0] != '-' || args[0][1] != '-')
|
||||
{
|
||||
char correct[GRUB_AUTH_MAX_PASSLEN];
|
||||
|
||||
grub_memset (correct, 0, sizeof (correct));
|
||||
grub_strncpy (correct, args[0], sizeof (correct));
|
||||
|
||||
return grub_crypto_memcmp (entered, correct, GRUB_AUTH_MAX_PASSLEN) == 0;
|
||||
}
|
||||
|
||||
pw = parse_legacy_md5 (argc, args);
|
||||
|
||||
if (!pw)
|
||||
return 0;
|
||||
|
||||
ret = check_password_md5_real (entered, pw);
|
||||
grub_free (pw);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_legacy_check_password (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
char entered[GRUB_AUTH_MAX_PASSLEN];
|
||||
|
||||
if (argc == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
|
||||
grub_puts_ (N_("Enter password: "));
|
||||
if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN))
|
||||
return GRUB_ACCESS_DENIED;
|
||||
|
||||
if (!grub_legacy_check_md5_password (argc, args,
|
||||
entered))
|
||||
return GRUB_ACCESS_DENIED;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_command_t cmd_source, cmd_configfile;
|
||||
static grub_command_t cmd_source_extract, cmd_configfile_extract;
|
||||
static grub_command_t cmd_kernel, cmd_initrd, cmd_initrdnounzip;
|
||||
static grub_command_t cmd_password, cmd_check_password;
|
||||
|
||||
GRUB_MOD_INIT(legacycfg)
|
||||
{
|
||||
cmd_source
|
||||
= grub_register_command ("legacy_source",
|
||||
grub_cmd_legacy_source,
|
||||
N_("FILE"),
|
||||
/* TRANSLATORS: "legacy config" means
|
||||
"config as used by grub-legacy". */
|
||||
N_("Parse legacy config in same context"));
|
||||
cmd_configfile
|
||||
= grub_register_command ("legacy_configfile",
|
||||
grub_cmd_legacy_source,
|
||||
N_("FILE"),
|
||||
N_("Parse legacy config in new context"));
|
||||
cmd_source_extract
|
||||
= grub_register_command ("extract_legacy_entries_source",
|
||||
grub_cmd_legacy_source,
|
||||
N_("FILE"),
|
||||
N_("Parse legacy config in same context taking only menu entries"));
|
||||
cmd_configfile_extract
|
||||
= grub_register_command ("extract_legacy_entries_configfile",
|
||||
grub_cmd_legacy_source,
|
||||
N_("FILE"),
|
||||
N_("Parse legacy config in new context taking only menu entries"));
|
||||
|
||||
cmd_kernel = grub_register_command ("legacy_kernel",
|
||||
grub_cmd_legacy_kernel,
|
||||
N_("[--no-mem-option] [--type=TYPE] FILE [ARG ...]"),
|
||||
N_("Simulate grub-legacy `kernel' command"));
|
||||
|
||||
cmd_initrd = grub_register_command ("legacy_initrd",
|
||||
grub_cmd_legacy_initrd,
|
||||
N_("FILE [ARG ...]"),
|
||||
N_("Simulate grub-legacy `initrd' command"));
|
||||
cmd_initrdnounzip = grub_register_command ("legacy_initrd_nounzip",
|
||||
grub_cmd_legacy_initrdnounzip,
|
||||
N_("FILE [ARG ...]"),
|
||||
N_("Simulate grub-legacy `modulenounzip' command"));
|
||||
|
||||
cmd_password = grub_register_command ("legacy_password",
|
||||
grub_cmd_legacy_password,
|
||||
N_("[--md5] PASSWD [FILE]"),
|
||||
N_("Simulate grub-legacy `password' command"));
|
||||
|
||||
cmd_check_password = grub_register_command ("legacy_check_password",
|
||||
grub_cmd_legacy_check_password,
|
||||
N_("[--md5] PASSWD [FILE]"),
|
||||
N_("Simulate grub-legacy `password' command in menu entry mode"));
|
||||
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(legacycfg)
|
||||
{
|
||||
grub_unregister_command (cmd_source);
|
||||
grub_unregister_command (cmd_configfile);
|
||||
grub_unregister_command (cmd_source_extract);
|
||||
grub_unregister_command (cmd_configfile_extract);
|
||||
|
||||
grub_unregister_command (cmd_kernel);
|
||||
grub_unregister_command (cmd_initrd);
|
||||
grub_unregister_command (cmd_initrdnounzip);
|
||||
|
||||
grub_unregister_command (cmd_password);
|
||||
grub_unregister_command (cmd_check_password);
|
||||
}
|
397
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/loadenv.c
Normal file
@@ -0,0 +1,397 @@
|
||||
/* loadenv.c - command to load/save environment variable. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008,2009,2010 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/dl.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/partition.h>
|
||||
#include <grub/lib/envblk.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
#include "loadenv.h"
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
/* TRANSLATORS: This option is used to override default filename
|
||||
for loading and storing environment. */
|
||||
{"file", 'f', 0, N_("Specify filename."), 0, ARG_TYPE_PATHNAME},
|
||||
{"skip-sig", 's', 0,
|
||||
N_("Skip signature-checking of the environment file."), 0, ARG_TYPE_NONE},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
/* Opens 'filename' with compression filters disabled. Optionally disables the
|
||||
PUBKEY filter (that insists upon properly signed files) as well. PUBKEY
|
||||
filter is restored before the function returns. */
|
||||
static grub_file_t
|
||||
open_envblk_file (char *filename,
|
||||
enum grub_file_type type)
|
||||
{
|
||||
grub_file_t file;
|
||||
char *buf = 0;
|
||||
|
||||
if (! filename)
|
||||
{
|
||||
const char *prefix;
|
||||
int len;
|
||||
|
||||
prefix = grub_env_get ("prefix");
|
||||
if (! prefix)
|
||||
{
|
||||
grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "prefix");
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = grub_strlen (prefix);
|
||||
buf = grub_malloc (len + 1 + sizeof (GRUB_ENVBLK_DEFCFG));
|
||||
if (! buf)
|
||||
return 0;
|
||||
filename = buf;
|
||||
|
||||
grub_strcpy (filename, prefix);
|
||||
filename[len] = '/';
|
||||
grub_strcpy (filename + len + 1, GRUB_ENVBLK_DEFCFG);
|
||||
}
|
||||
|
||||
file = grub_file_open (filename, type);
|
||||
|
||||
grub_free (buf);
|
||||
return file;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_load_env (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
grub_file_t file;
|
||||
grub_envblk_t envblk;
|
||||
grub_env_whitelist_t whitelist;
|
||||
|
||||
whitelist.len = argc;
|
||||
whitelist.list = args;
|
||||
|
||||
/* state[0] is the -f flag; state[1] is the --skip-sig flag */
|
||||
file = open_envblk_file ((state[0].set) ? state[0].arg : 0,
|
||||
GRUB_FILE_TYPE_LOADENV
|
||||
| (state[1].set
|
||||
? GRUB_FILE_TYPE_SKIP_SIGNATURE : GRUB_FILE_TYPE_NONE));
|
||||
if (! file)
|
||||
return grub_errno;
|
||||
|
||||
envblk = read_envblk_file (file);
|
||||
if (! envblk)
|
||||
goto fail;
|
||||
|
||||
/* argc > 0 indicates caller provided a whitelist of variables to read. */
|
||||
grub_envblk_iterate (envblk, argc > 0 ? &whitelist : 0, set_var);
|
||||
grub_envblk_close (envblk);
|
||||
|
||||
fail:
|
||||
grub_file_close (file);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
/* Print all variables in current context. */
|
||||
static int
|
||||
print_var (const char *name, const char *value,
|
||||
void *hook_data __attribute__ ((unused)))
|
||||
{
|
||||
grub_printf ("%s=%s\n", name, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_list_env (grub_extcmd_context_t ctxt,
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
grub_file_t file;
|
||||
grub_envblk_t envblk;
|
||||
|
||||
file = open_envblk_file ((state[0].set) ? state[0].arg : 0,
|
||||
GRUB_FILE_TYPE_LOADENV
|
||||
| (state[1].set
|
||||
? GRUB_FILE_TYPE_SKIP_SIGNATURE : GRUB_FILE_TYPE_NONE));
|
||||
if (! file)
|
||||
return grub_errno;
|
||||
|
||||
envblk = read_envblk_file (file);
|
||||
if (! envblk)
|
||||
goto fail;
|
||||
|
||||
grub_envblk_iterate (envblk, NULL, print_var);
|
||||
grub_envblk_close (envblk);
|
||||
|
||||
fail:
|
||||
grub_file_close (file);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
/* Used to maintain a variable length of blocklists internally. */
|
||||
struct blocklist
|
||||
{
|
||||
grub_disk_addr_t sector;
|
||||
unsigned offset;
|
||||
unsigned length;
|
||||
struct blocklist *next;
|
||||
};
|
||||
|
||||
static void
|
||||
free_blocklists (struct blocklist *p)
|
||||
{
|
||||
struct blocklist *q;
|
||||
|
||||
for (; p; p = q)
|
||||
{
|
||||
q = p->next;
|
||||
grub_free (p);
|
||||
}
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
check_blocklists (grub_envblk_t envblk, struct blocklist *blocklists,
|
||||
grub_file_t file)
|
||||
{
|
||||
grub_size_t total_length;
|
||||
grub_size_t index;
|
||||
grub_disk_t disk;
|
||||
grub_disk_addr_t part_start;
|
||||
struct blocklist *p;
|
||||
char *buf;
|
||||
|
||||
/* Sanity checks. */
|
||||
total_length = 0;
|
||||
for (p = blocklists; p; p = p->next)
|
||||
{
|
||||
struct blocklist *q;
|
||||
/* Check if any pair of blocks overlap. */
|
||||
for (q = p->next; q; q = q->next)
|
||||
{
|
||||
grub_disk_addr_t s1, s2;
|
||||
grub_disk_addr_t e1, e2;
|
||||
|
||||
s1 = p->sector;
|
||||
e1 = s1 + ((p->length + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS);
|
||||
|
||||
s2 = q->sector;
|
||||
e2 = s2 + ((q->length + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS);
|
||||
|
||||
if (s1 < e2 && s2 < e1)
|
||||
{
|
||||
/* This might be actually valid, but it is unbelievable that
|
||||
any filesystem makes such a silly allocation. */
|
||||
return grub_error (GRUB_ERR_BAD_FS, "malformed file");
|
||||
}
|
||||
}
|
||||
|
||||
total_length += p->length;
|
||||
}
|
||||
|
||||
if (total_length != grub_file_size (file))
|
||||
{
|
||||
/* Maybe sparse, unallocated sectors. No way in GRUB. */
|
||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "sparse file not allowed");
|
||||
}
|
||||
|
||||
/* One more sanity check. Re-read all sectors by blocklists, and compare
|
||||
those with the data read via a file. */
|
||||
disk = file->device->disk;
|
||||
|
||||
part_start = grub_partition_get_start (disk->partition);
|
||||
|
||||
buf = grub_envblk_buffer (envblk);
|
||||
char *blockbuf = NULL;
|
||||
grub_size_t blockbuf_len = 0;
|
||||
for (p = blocklists, index = 0; p; index += p->length, p = p->next)
|
||||
{
|
||||
if (p->length > blockbuf_len)
|
||||
{
|
||||
grub_free (blockbuf);
|
||||
blockbuf_len = 2 * p->length;
|
||||
blockbuf = grub_malloc (blockbuf_len);
|
||||
if (!blockbuf)
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
if (grub_disk_read (disk, p->sector - part_start,
|
||||
p->offset, p->length, blockbuf))
|
||||
return grub_errno;
|
||||
|
||||
if (grub_memcmp (buf + index, blockbuf, p->length) != 0)
|
||||
return grub_error (GRUB_ERR_FILE_READ_ERROR, "invalid blocklist");
|
||||
}
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static int
|
||||
write_blocklists (grub_envblk_t envblk, struct blocklist *blocklists,
|
||||
grub_file_t file)
|
||||
{
|
||||
char *buf;
|
||||
grub_disk_t disk;
|
||||
grub_disk_addr_t part_start;
|
||||
struct blocklist *p;
|
||||
grub_size_t index;
|
||||
|
||||
buf = grub_envblk_buffer (envblk);
|
||||
disk = file->device->disk;
|
||||
part_start = grub_partition_get_start (disk->partition);
|
||||
|
||||
index = 0;
|
||||
for (p = blocklists; p; index += p->length, p = p->next)
|
||||
{
|
||||
if (grub_disk_write (disk, p->sector - part_start,
|
||||
p->offset, p->length, buf + index))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Context for grub_cmd_save_env. */
|
||||
struct grub_cmd_save_env_ctx
|
||||
{
|
||||
struct blocklist *head, *tail;
|
||||
};
|
||||
|
||||
/* Store blocklists in a linked list. */
|
||||
static void
|
||||
save_env_read_hook (grub_disk_addr_t sector, unsigned offset, unsigned length,
|
||||
void *data)
|
||||
{
|
||||
struct grub_cmd_save_env_ctx *ctx = data;
|
||||
struct blocklist *block;
|
||||
|
||||
block = grub_malloc (sizeof (*block));
|
||||
if (! block)
|
||||
return;
|
||||
|
||||
block->sector = sector;
|
||||
block->offset = offset;
|
||||
block->length = length;
|
||||
|
||||
/* Slightly complicated, because the list should be FIFO. */
|
||||
block->next = 0;
|
||||
if (ctx->tail)
|
||||
ctx->tail->next = block;
|
||||
ctx->tail = block;
|
||||
if (! ctx->head)
|
||||
ctx->head = block;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_save_env (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
grub_file_t file;
|
||||
grub_envblk_t envblk;
|
||||
struct grub_cmd_save_env_ctx ctx = {
|
||||
.head = 0,
|
||||
.tail = 0
|
||||
};
|
||||
|
||||
if (! argc)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no variable is specified");
|
||||
|
||||
file = open_envblk_file ((state[0].set) ? state[0].arg : 0,
|
||||
GRUB_FILE_TYPE_SAVEENV
|
||||
| GRUB_FILE_TYPE_SKIP_SIGNATURE);
|
||||
if (! file)
|
||||
return grub_errno;
|
||||
|
||||
if (! file->device->disk)
|
||||
{
|
||||
grub_file_close (file);
|
||||
return grub_error (GRUB_ERR_BAD_DEVICE, "disk device required");
|
||||
}
|
||||
|
||||
file->read_hook = save_env_read_hook;
|
||||
file->read_hook_data = &ctx;
|
||||
envblk = read_envblk_file (file);
|
||||
file->read_hook = 0;
|
||||
if (! envblk)
|
||||
goto fail;
|
||||
|
||||
if (check_blocklists (envblk, ctx.head, file))
|
||||
goto fail;
|
||||
|
||||
while (argc)
|
||||
{
|
||||
const char *value;
|
||||
|
||||
value = grub_env_get (args[0]);
|
||||
if (value)
|
||||
{
|
||||
if (! grub_envblk_set (envblk, args[0], value))
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "environment block too small");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else
|
||||
grub_envblk_delete (envblk, args[0]);
|
||||
|
||||
argc--;
|
||||
args++;
|
||||
}
|
||||
|
||||
write_blocklists (envblk, ctx.head, file);
|
||||
|
||||
fail:
|
||||
if (envblk)
|
||||
grub_envblk_close (envblk);
|
||||
free_blocklists (ctx.head);
|
||||
grub_file_close (file);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd_load, cmd_list, cmd_save;
|
||||
|
||||
GRUB_MOD_INIT(loadenv)
|
||||
{
|
||||
cmd_load =
|
||||
grub_register_extcmd ("load_env", grub_cmd_load_env, 0,
|
||||
N_("[-f FILE] [-s|--skip-sig] [variable_name_to_whitelist] [...]"),
|
||||
N_("Load variables from environment block file."),
|
||||
options);
|
||||
cmd_list =
|
||||
grub_register_extcmd ("list_env", grub_cmd_list_env, 0, N_("[-f FILE]"),
|
||||
N_("List variables from environment block file."),
|
||||
options);
|
||||
cmd_save =
|
||||
grub_register_extcmd ("save_env", grub_cmd_save_env, 0,
|
||||
N_("[-f FILE] variable_name [...]"),
|
||||
N_("Save variables to environment block file."),
|
||||
options);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(loadenv)
|
||||
{
|
||||
grub_unregister_extcmd (cmd_load);
|
||||
grub_unregister_extcmd (cmd_list);
|
||||
grub_unregister_extcmd (cmd_save);
|
||||
}
|
93
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/loadenv.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/* loadenv.c - command to load/save environment variable. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008,2009,2010 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
static grub_envblk_t UNUSED
|
||||
read_envblk_file (grub_file_t file)
|
||||
{
|
||||
grub_off_t offset = 0;
|
||||
char *buf;
|
||||
grub_size_t size = grub_file_size (file);
|
||||
grub_envblk_t envblk;
|
||||
|
||||
buf = grub_malloc (size);
|
||||
if (! buf)
|
||||
return 0;
|
||||
|
||||
while (size > 0)
|
||||
{
|
||||
grub_ssize_t ret;
|
||||
|
||||
ret = grub_file_read (file, buf + offset, size);
|
||||
if (ret <= 0)
|
||||
{
|
||||
grub_free (buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size -= ret;
|
||||
offset += ret;
|
||||
}
|
||||
|
||||
envblk = grub_envblk_open (buf, offset);
|
||||
if (! envblk)
|
||||
{
|
||||
grub_free (buf);
|
||||
grub_error (GRUB_ERR_BAD_FILE_TYPE, "invalid environment block");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return envblk;
|
||||
}
|
||||
|
||||
struct grub_env_whitelist
|
||||
{
|
||||
grub_size_t len;
|
||||
char **list;
|
||||
};
|
||||
typedef struct grub_env_whitelist grub_env_whitelist_t;
|
||||
|
||||
static int UNUSED
|
||||
test_whitelist_membership (const char* name,
|
||||
const grub_env_whitelist_t* whitelist)
|
||||
{
|
||||
grub_size_t i;
|
||||
|
||||
for (i = 0; i < whitelist->len; i++)
|
||||
if (grub_strcmp (name, whitelist->list[i]) == 0)
|
||||
return 1; /* found it */
|
||||
|
||||
return 0; /* not found */
|
||||
}
|
||||
|
||||
/* Helper for grub_cmd_load_env. */
|
||||
static int UNUSED
|
||||
set_var (const char *name, const char *value, void *whitelist)
|
||||
{
|
||||
if (! whitelist)
|
||||
{
|
||||
grub_env_set (name, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (test_whitelist_membership (name,
|
||||
(const grub_env_whitelist_t *) whitelist))
|
||||
grub_env_set (name, value);
|
||||
|
||||
return 0;
|
||||
}
|
349
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/menuentry.c
Normal file
@@ -0,0 +1,349 @@
|
||||
/* menuentry.c - menuentry command */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/types.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/normal.h>
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{"class", 1, GRUB_ARG_OPTION_REPEATABLE,
|
||||
N_("Menu entry type."), N_("STRING"), ARG_TYPE_STRING},
|
||||
{"users", 2, 0,
|
||||
N_("List of users allowed to boot this entry."), N_("USERNAME[,USERNAME]"),
|
||||
ARG_TYPE_STRING},
|
||||
{"hotkey", 3, 0,
|
||||
N_("Keyboard key to quickly boot this entry."), N_("KEYBOARD_KEY"), ARG_TYPE_STRING},
|
||||
{"source", 4, 0,
|
||||
N_("Use STRING as menu entry body."), N_("STRING"), ARG_TYPE_STRING},
|
||||
{"id", 0, 0, N_("Menu entry identifier."), N_("STRING"), ARG_TYPE_STRING},
|
||||
/* TRANSLATORS: menu entry can either be bootable by anyone or only by
|
||||
handful of users. By default when security is active only superusers can
|
||||
boot a given menu entry. With --unrestricted (this option)
|
||||
anyone can boot it. */
|
||||
{"unrestricted", 0, 0, N_("This entry can be booted by any user."),
|
||||
0, ARG_TYPE_NONE},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static struct
|
||||
{
|
||||
const char *name;
|
||||
int key;
|
||||
} hotkey_aliases[] =
|
||||
{
|
||||
{"backspace", GRUB_TERM_BACKSPACE},
|
||||
{"tab", GRUB_TERM_TAB},
|
||||
{"delete", GRUB_TERM_KEY_DC},
|
||||
{"insert", GRUB_TERM_KEY_INSERT},
|
||||
{"f1", GRUB_TERM_KEY_F1},
|
||||
{"f2", GRUB_TERM_KEY_F2},
|
||||
{"f3", GRUB_TERM_KEY_F3},
|
||||
{"f4", GRUB_TERM_KEY_F4},
|
||||
{"f5", GRUB_TERM_KEY_F5},
|
||||
{"f6", GRUB_TERM_KEY_F6},
|
||||
{"f7", GRUB_TERM_KEY_F7},
|
||||
{"f8", GRUB_TERM_KEY_F8},
|
||||
{"f9", GRUB_TERM_KEY_F9},
|
||||
{"f10", GRUB_TERM_KEY_F10},
|
||||
{"f11", GRUB_TERM_KEY_F11},
|
||||
{"f12", GRUB_TERM_KEY_F12},
|
||||
};
|
||||
|
||||
/* Add a menu entry to the current menu context (as given by the environment
|
||||
variable data slot `menu'). As the configuration file is read, the script
|
||||
parser calls this when a menu entry is to be created. */
|
||||
grub_err_t
|
||||
grub_normal_add_menu_entry (int argc, const char **args,
|
||||
char **classes, const char *id,
|
||||
const char *users, const char *hotkey,
|
||||
const char *prefix, const char *sourcecode,
|
||||
int submenu, int *index, struct bls_entry *bls)
|
||||
{
|
||||
int menu_hotkey = 0;
|
||||
char **menu_args = NULL;
|
||||
char *menu_users = NULL;
|
||||
char *menu_title = NULL;
|
||||
char *menu_sourcecode = NULL;
|
||||
char *menu_id = NULL;
|
||||
struct grub_menu_entry_class *menu_classes = NULL;
|
||||
|
||||
grub_menu_t menu;
|
||||
grub_menu_entry_t *last;
|
||||
|
||||
menu = grub_env_get_menu ();
|
||||
if (! menu)
|
||||
return grub_error (GRUB_ERR_MENU, "no menu context");
|
||||
|
||||
last = &menu->entry_list;
|
||||
|
||||
menu_sourcecode = grub_xasprintf ("%s%s", prefix ?: "", sourcecode);
|
||||
if (! menu_sourcecode)
|
||||
return grub_errno;
|
||||
|
||||
if (classes && classes[0])
|
||||
{
|
||||
int i;
|
||||
for (i = 0; classes[i]; i++); /* count # of menuentry classes */
|
||||
menu_classes = grub_zalloc (sizeof (struct grub_menu_entry_class)
|
||||
* (i + 1));
|
||||
if (! menu_classes)
|
||||
goto fail;
|
||||
|
||||
for (i = 0; classes[i]; i++)
|
||||
{
|
||||
menu_classes[i].name = grub_strdup (classes[i]);
|
||||
if (! menu_classes[i].name)
|
||||
goto fail;
|
||||
menu_classes[i].next = classes[i + 1] ? &menu_classes[i + 1] : NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (users)
|
||||
{
|
||||
menu_users = grub_strdup (users);
|
||||
if (! menu_users)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (hotkey)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < ARRAY_SIZE (hotkey_aliases); i++)
|
||||
if (grub_strcmp (hotkey, hotkey_aliases[i].name) == 0)
|
||||
{
|
||||
menu_hotkey = hotkey_aliases[i].key;
|
||||
break;
|
||||
}
|
||||
if (i == ARRAY_SIZE (hotkey_aliases))
|
||||
menu_hotkey = hotkey[0];
|
||||
}
|
||||
|
||||
if (! argc)
|
||||
{
|
||||
grub_error (GRUB_ERR_MENU, "menuentry is missing title");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
menu_title = grub_strdup (args[0]);
|
||||
if (! menu_title)
|
||||
goto fail;
|
||||
|
||||
grub_dprintf ("menu", "id:\"%s\"\n", id);
|
||||
grub_dprintf ("menu", "title:\"%s\"\n", menu_title);
|
||||
menu_id = grub_strdup (id ? : menu_title);
|
||||
if (! menu_id)
|
||||
goto fail;
|
||||
grub_dprintf ("menu", "menu_id:\"%s\"\n", menu_id);
|
||||
|
||||
/* Save argc, args to pass as parameters to block arg later. */
|
||||
menu_args = grub_malloc (sizeof (char*) * (argc + 1));
|
||||
if (! menu_args)
|
||||
goto fail;
|
||||
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
menu_args[i] = grub_strdup (args[i]);
|
||||
if (! menu_args[i])
|
||||
goto fail;
|
||||
}
|
||||
menu_args[argc] = NULL;
|
||||
}
|
||||
|
||||
/* Add the menu entry at the end of the list. */
|
||||
int ind=0;
|
||||
while (*last)
|
||||
{
|
||||
ind++;
|
||||
last = &(*last)->next;
|
||||
}
|
||||
|
||||
*last = grub_zalloc (sizeof (**last));
|
||||
if (! *last)
|
||||
goto fail;
|
||||
|
||||
(*last)->title = menu_title;
|
||||
(*last)->id = menu_id;
|
||||
(*last)->hotkey = menu_hotkey;
|
||||
(*last)->classes = menu_classes;
|
||||
if (menu_users)
|
||||
(*last)->restricted = 1;
|
||||
(*last)->users = menu_users;
|
||||
(*last)->argc = argc;
|
||||
(*last)->args = menu_args;
|
||||
(*last)->sourcecode = menu_sourcecode;
|
||||
(*last)->submenu = submenu;
|
||||
(*last)->bls = bls;
|
||||
|
||||
menu->size++;
|
||||
if (index)
|
||||
*index = ind;
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
fail:
|
||||
|
||||
grub_free (menu_sourcecode);
|
||||
{
|
||||
int i;
|
||||
for (i = 0; menu_classes && menu_classes[i].name; i++)
|
||||
grub_free (menu_classes[i].name);
|
||||
grub_free (menu_classes);
|
||||
}
|
||||
|
||||
{
|
||||
int i;
|
||||
for (i = 0; menu_args && menu_args[i]; i++)
|
||||
grub_free (menu_args[i]);
|
||||
grub_free (menu_args);
|
||||
}
|
||||
|
||||
grub_free (menu_users);
|
||||
grub_free (menu_title);
|
||||
grub_free (menu_id);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static char *
|
||||
setparams_prefix (int argc, char **args)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
char *p;
|
||||
char *result;
|
||||
grub_size_t len = 10;
|
||||
|
||||
/* Count resulting string length */
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
len += 3; /* 3 = 1 space + 2 quotes */
|
||||
p = args[i];
|
||||
while (*p)
|
||||
len += (*p++ == '\'' ? 3 : 1);
|
||||
}
|
||||
|
||||
result = grub_malloc (len + 2);
|
||||
if (! result)
|
||||
return 0;
|
||||
|
||||
grub_strcpy (result, "setparams");
|
||||
p = result + 9;
|
||||
|
||||
for (j = 0; j < argc; j++)
|
||||
{
|
||||
*p++ = ' ';
|
||||
*p++ = '\'';
|
||||
p = grub_strchrsub (p, args[j], '\'', "'\\''");
|
||||
*p++ = '\'';
|
||||
}
|
||||
*p++ = '\n';
|
||||
*p = '\0';
|
||||
return result;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
char ch;
|
||||
char *src;
|
||||
char *prefix;
|
||||
unsigned len;
|
||||
grub_err_t r;
|
||||
const char *users;
|
||||
|
||||
if (! argc)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing arguments");
|
||||
|
||||
if (ctxt->state[3].set && ctxt->script)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "multiple menuentry definitions");
|
||||
|
||||
if (! ctxt->state[3].set && ! ctxt->script)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no menuentry definition");
|
||||
|
||||
if (ctxt->state[1].set)
|
||||
users = ctxt->state[1].arg;
|
||||
else if (ctxt->state[5].set)
|
||||
users = NULL;
|
||||
else
|
||||
users = "";
|
||||
|
||||
if (! ctxt->script)
|
||||
return grub_normal_add_menu_entry (argc, (const char **) args,
|
||||
(ctxt->state[0].set ? ctxt->state[0].args
|
||||
: NULL),
|
||||
ctxt->state[4].arg,
|
||||
users,
|
||||
ctxt->state[2].arg, 0,
|
||||
ctxt->state[3].arg,
|
||||
ctxt->extcmd->cmd->name[0] == 's',
|
||||
NULL, NULL);
|
||||
|
||||
src = args[argc - 1];
|
||||
args[argc - 1] = NULL;
|
||||
|
||||
len = grub_strlen(src);
|
||||
ch = src[len - 1];
|
||||
src[len - 1] = '\0';
|
||||
|
||||
prefix = setparams_prefix (argc - 1, args);
|
||||
if (! prefix)
|
||||
return grub_errno;
|
||||
|
||||
r = grub_normal_add_menu_entry (argc - 1, (const char **) args,
|
||||
ctxt->state[0].args, ctxt->state[4].arg,
|
||||
users,
|
||||
ctxt->state[2].arg, prefix, src + 1,
|
||||
ctxt->extcmd->cmd->name[0] == 's', NULL,
|
||||
NULL);
|
||||
|
||||
src[len - 1] = ch;
|
||||
args[argc - 1] = src;
|
||||
grub_free (prefix);
|
||||
return r;
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd, cmd_sub;
|
||||
|
||||
void
|
||||
grub_menu_init (void)
|
||||
{
|
||||
cmd = grub_register_extcmd ("menuentry", grub_cmd_menuentry,
|
||||
GRUB_COMMAND_FLAG_BLOCKS
|
||||
| GRUB_COMMAND_ACCEPT_DASH
|
||||
| GRUB_COMMAND_FLAG_EXTRACTOR,
|
||||
N_("BLOCK"), N_("Define a menu entry."), options);
|
||||
cmd_sub = grub_register_extcmd ("submenu", grub_cmd_menuentry,
|
||||
GRUB_COMMAND_FLAG_BLOCKS
|
||||
| GRUB_COMMAND_ACCEPT_DASH
|
||||
| GRUB_COMMAND_FLAG_EXTRACTOR,
|
||||
N_("BLOCK"), N_("Define a submenu."),
|
||||
options);
|
||||
}
|
||||
|
||||
void
|
||||
grub_menu_fini (void)
|
||||
{
|
||||
grub_unregister_extcmd (cmd);
|
||||
grub_unregister_extcmd (cmd_sub);
|
||||
}
|
353
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/search.c
Normal file
@@ -0,0 +1,353 @@
|
||||
/* search.c - search devices based on a file or a filesystem label */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2005,2007,2008,2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/types.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/device.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/search.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/partition.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static int g_no_vtoyefi_part = 0;
|
||||
static char g_vtoyefi_dosname[64];
|
||||
static char g_vtoyefi_gptname[64];
|
||||
|
||||
struct cache_entry
|
||||
{
|
||||
struct cache_entry *next;
|
||||
char *key;
|
||||
char *value;
|
||||
};
|
||||
|
||||
static struct cache_entry *cache;
|
||||
|
||||
/* Context for FUNC_NAME. */
|
||||
struct search_ctx
|
||||
{
|
||||
const char *key;
|
||||
const char *var;
|
||||
int no_floppy;
|
||||
char **hints;
|
||||
unsigned nhints;
|
||||
int count;
|
||||
int is_cache;
|
||||
};
|
||||
|
||||
/* Helper for FUNC_NAME. */
|
||||
static int
|
||||
iterate_device (const char *name, void *data)
|
||||
{
|
||||
struct search_ctx *ctx = data;
|
||||
int found = 0;
|
||||
|
||||
/* Skip floppy drives when requested. */
|
||||
if (ctx->no_floppy &&
|
||||
name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9')
|
||||
return 1;
|
||||
|
||||
if (g_no_vtoyefi_part && (grub_strcmp(name, g_vtoyefi_dosname) == 0 || grub_strcmp(name, g_vtoyefi_gptname) == 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DO_SEARCH_FS_UUID
|
||||
#define compare_fn grub_strcasecmp
|
||||
#else
|
||||
#define compare_fn grub_strcmp
|
||||
#endif
|
||||
|
||||
#ifdef DO_SEARCH_FILE
|
||||
{
|
||||
char *buf;
|
||||
grub_file_t file;
|
||||
|
||||
buf = grub_xasprintf ("(%s)%s", name, ctx->key);
|
||||
if (! buf)
|
||||
return 1;
|
||||
|
||||
file = grub_file_open (buf, GRUB_FILE_TYPE_FS_SEARCH
|
||||
| GRUB_FILE_TYPE_NO_DECOMPRESS);
|
||||
if (file)
|
||||
{
|
||||
found = 1;
|
||||
grub_file_close (file);
|
||||
}
|
||||
grub_free (buf);
|
||||
}
|
||||
#else
|
||||
{
|
||||
/* SEARCH_FS_UUID or SEARCH_LABEL */
|
||||
grub_device_t dev;
|
||||
grub_fs_t fs;
|
||||
char *quid;
|
||||
|
||||
dev = grub_device_open (name);
|
||||
if (dev)
|
||||
{
|
||||
fs = grub_fs_probe (dev);
|
||||
|
||||
#ifdef DO_SEARCH_FS_UUID
|
||||
#define read_fn fs_uuid
|
||||
#else
|
||||
#define read_fn fs_label
|
||||
#endif
|
||||
|
||||
if (fs && fs->read_fn)
|
||||
{
|
||||
fs->read_fn (dev, &quid);
|
||||
|
||||
if (grub_errno == GRUB_ERR_NONE && quid)
|
||||
{
|
||||
if (compare_fn (quid, ctx->key) == 0)
|
||||
found = 1;
|
||||
|
||||
grub_free (quid);
|
||||
}
|
||||
}
|
||||
|
||||
grub_device_close (dev);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!ctx->is_cache && found && ctx->count == 0)
|
||||
{
|
||||
struct cache_entry *cache_ent;
|
||||
cache_ent = grub_malloc (sizeof (*cache_ent));
|
||||
if (cache_ent)
|
||||
{
|
||||
cache_ent->key = grub_strdup (ctx->key);
|
||||
cache_ent->value = grub_strdup (name);
|
||||
if (cache_ent->value && cache_ent->key)
|
||||
{
|
||||
cache_ent->next = cache;
|
||||
cache = cache_ent;
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_free (cache_ent->value);
|
||||
grub_free (cache_ent->key);
|
||||
grub_free (cache_ent);
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
}
|
||||
else
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
ctx->count++;
|
||||
if (ctx->var)
|
||||
grub_env_set (ctx->var, name);
|
||||
else
|
||||
grub_printf (" %s", name);
|
||||
}
|
||||
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
return (found && ctx->var);
|
||||
}
|
||||
|
||||
/* Helper for FUNC_NAME. */
|
||||
static int
|
||||
part_hook (grub_disk_t disk, const grub_partition_t partition, void *data)
|
||||
{
|
||||
struct search_ctx *ctx = data;
|
||||
char *partition_name, *devname;
|
||||
int ret;
|
||||
|
||||
partition_name = grub_partition_get_name (partition);
|
||||
if (! partition_name)
|
||||
return 1;
|
||||
|
||||
devname = grub_xasprintf ("%s,%s", disk->name, partition_name);
|
||||
grub_free (partition_name);
|
||||
if (!devname)
|
||||
return 1;
|
||||
ret = iterate_device (devname, ctx);
|
||||
grub_free (devname);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Helper for FUNC_NAME. */
|
||||
static void
|
||||
try (struct search_ctx *ctx)
|
||||
{
|
||||
unsigned i;
|
||||
struct cache_entry **prev;
|
||||
struct cache_entry *cache_ent;
|
||||
|
||||
for (prev = &cache, cache_ent = *prev; cache_ent;
|
||||
prev = &cache_ent->next, cache_ent = *prev)
|
||||
if (compare_fn (cache_ent->key, ctx->key) == 0)
|
||||
break;
|
||||
if (cache_ent)
|
||||
{
|
||||
ctx->is_cache = 1;
|
||||
if (iterate_device (cache_ent->value, ctx))
|
||||
{
|
||||
ctx->is_cache = 0;
|
||||
return;
|
||||
}
|
||||
ctx->is_cache = 0;
|
||||
/* Cache entry was outdated. Remove it. */
|
||||
if (!ctx->count)
|
||||
{
|
||||
*prev = cache_ent->next;
|
||||
grub_free (cache_ent->key);
|
||||
grub_free (cache_ent->value);
|
||||
grub_free (cache_ent);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ctx->nhints; i++)
|
||||
{
|
||||
char *end;
|
||||
if (!ctx->hints[i][0])
|
||||
continue;
|
||||
end = ctx->hints[i] + grub_strlen (ctx->hints[i]) - 1;
|
||||
if (*end == ',')
|
||||
*end = 0;
|
||||
if (iterate_device (ctx->hints[i], ctx))
|
||||
{
|
||||
if (!*end)
|
||||
*end = ',';
|
||||
return;
|
||||
}
|
||||
if (!*end)
|
||||
{
|
||||
grub_device_t dev;
|
||||
int ret;
|
||||
dev = grub_device_open (ctx->hints[i]);
|
||||
if (!dev)
|
||||
{
|
||||
if (!*end)
|
||||
*end = ',';
|
||||
continue;
|
||||
}
|
||||
if (!dev->disk)
|
||||
{
|
||||
grub_device_close (dev);
|
||||
if (!*end)
|
||||
*end = ',';
|
||||
continue;
|
||||
}
|
||||
ret = grub_partition_iterate (dev->disk, part_hook, ctx);
|
||||
if (!*end)
|
||||
*end = ',';
|
||||
grub_device_close (dev);
|
||||
if (ret)
|
||||
return;
|
||||
}
|
||||
}
|
||||
grub_device_iterate (iterate_device, ctx);
|
||||
}
|
||||
|
||||
void
|
||||
FUNC_NAME (const char *key, const char *var, int no_floppy,
|
||||
char **hints, unsigned nhints)
|
||||
{
|
||||
struct search_ctx ctx = {
|
||||
.key = key,
|
||||
.var = var,
|
||||
.no_floppy = no_floppy,
|
||||
.hints = hints,
|
||||
.nhints = nhints,
|
||||
.count = 0,
|
||||
.is_cache = 0
|
||||
};
|
||||
grub_fs_autoload_hook_t saved_autoload;
|
||||
|
||||
g_no_vtoyefi_part = 0;
|
||||
if (grub_env_get("VTOY_SEARCH_NO_VTOYEFI"))
|
||||
{
|
||||
grub_snprintf(g_vtoyefi_dosname, sizeof(g_vtoyefi_dosname), "%s,msdos2", grub_env_get("vtoydev"));
|
||||
grub_snprintf(g_vtoyefi_gptname, sizeof(g_vtoyefi_gptname), "%s,gpt2", grub_env_get("vtoydev"));
|
||||
g_no_vtoyefi_part = 1;
|
||||
}
|
||||
|
||||
/* First try without autoloading if we're setting variable. */
|
||||
if (var)
|
||||
{
|
||||
saved_autoload = grub_fs_autoload_hook;
|
||||
grub_fs_autoload_hook = 0;
|
||||
try (&ctx);
|
||||
|
||||
/* Restore autoload hook. */
|
||||
grub_fs_autoload_hook = saved_autoload;
|
||||
|
||||
/* Retry with autoload if nothing found. */
|
||||
if (grub_errno == GRUB_ERR_NONE && ctx.count == 0)
|
||||
try (&ctx);
|
||||
}
|
||||
else
|
||||
try (&ctx);
|
||||
|
||||
if (grub_errno == GRUB_ERR_NONE && ctx.count == 0)
|
||||
grub_error (GRUB_ERR_FILE_NOT_FOUND, "no such device: %s", key);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_do_search (grub_command_t cmd __attribute__ ((unused)), int argc,
|
||||
char **args)
|
||||
{
|
||||
if (argc == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
|
||||
|
||||
FUNC_NAME (args[0], argc == 1 ? 0 : args[1], 0, (args + 2),
|
||||
argc > 2 ? argc - 2 : 0);
|
||||
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
#ifdef DO_SEARCH_FILE
|
||||
GRUB_MOD_INIT(search_fs_file)
|
||||
#elif defined (DO_SEARCH_FS_UUID)
|
||||
GRUB_MOD_INIT(search_fs_uuid)
|
||||
#else
|
||||
GRUB_MOD_INIT(search_label)
|
||||
#endif
|
||||
{
|
||||
cmd =
|
||||
grub_register_command (COMMAND_NAME, grub_cmd_do_search,
|
||||
N_("NAME [VARIABLE] [HINTS]"),
|
||||
HELP_MESSAGE);
|
||||
}
|
||||
|
||||
#ifdef DO_SEARCH_FILE
|
||||
GRUB_MOD_FINI(search_fs_file)
|
||||
#elif defined (DO_SEARCH_FS_UUID)
|
||||
GRUB_MOD_FINI(search_fs_uuid)
|
||||
#else
|
||||
GRUB_MOD_FINI(search_label)
|
||||
#endif
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
491
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/test.c
Normal file
@@ -0,0 +1,491 @@
|
||||
/* test.c -- The test command.. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2005,2007,2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/dl.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/fs.h>
|
||||
#include <grub/device.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static int g_test_case_insensitive = 0;
|
||||
|
||||
/* A simple implementation for signed numbers. */
|
||||
static int
|
||||
grub_strtosl (char *arg, char **end, int base)
|
||||
{
|
||||
if (arg[0] == '-')
|
||||
return -grub_strtoul (arg + 1, end, base);
|
||||
return grub_strtoul (arg, end, base);
|
||||
}
|
||||
|
||||
/* Context for test_parse. */
|
||||
struct test_parse_ctx
|
||||
{
|
||||
int invert;
|
||||
int or, and;
|
||||
int file_exists;
|
||||
struct grub_dirhook_info file_info;
|
||||
char *filename;
|
||||
};
|
||||
|
||||
/* Take care of discarding and inverting. */
|
||||
static void
|
||||
update_val (int val, struct test_parse_ctx *ctx)
|
||||
{
|
||||
ctx->and = ctx->and && (ctx->invert ? ! val : val);
|
||||
ctx->invert = 0;
|
||||
}
|
||||
|
||||
/* A hook for iterating directories. */
|
||||
static int
|
||||
find_file (const char *cur_filename, const struct grub_dirhook_info *info,
|
||||
void *data)
|
||||
{
|
||||
int case_insensitive = 0;
|
||||
struct test_parse_ctx *ctx = data;
|
||||
|
||||
if (g_test_case_insensitive || info->case_insensitive)
|
||||
case_insensitive = 1;
|
||||
|
||||
if ((case_insensitive ? grub_strcasecmp (cur_filename, ctx->filename)
|
||||
: grub_strcmp (cur_filename, ctx->filename)) == 0)
|
||||
{
|
||||
ctx->file_info = *info;
|
||||
ctx->file_exists = 1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check if file exists and fetch its information. */
|
||||
static void
|
||||
get_fileinfo (char *path, struct test_parse_ctx *ctx)
|
||||
{
|
||||
char *pathname;
|
||||
char *device_name;
|
||||
grub_fs_t fs;
|
||||
grub_device_t dev;
|
||||
|
||||
ctx->file_exists = 0;
|
||||
device_name = grub_file_get_device_name (path);
|
||||
dev = grub_device_open (device_name);
|
||||
if (! dev)
|
||||
{
|
||||
grub_free (device_name);
|
||||
return;
|
||||
}
|
||||
|
||||
fs = grub_fs_probe (dev);
|
||||
if (! fs)
|
||||
{
|
||||
grub_free (device_name);
|
||||
grub_device_close (dev);
|
||||
return;
|
||||
}
|
||||
|
||||
pathname = grub_strchr (path, ')');
|
||||
if (! pathname)
|
||||
pathname = path;
|
||||
else
|
||||
pathname++;
|
||||
|
||||
/* Remove trailing '/'. */
|
||||
while (*pathname && pathname[grub_strlen (pathname) - 1] == '/')
|
||||
pathname[grub_strlen (pathname) - 1] = 0;
|
||||
|
||||
/* Split into path and filename. */
|
||||
ctx->filename = grub_strrchr (pathname, '/');
|
||||
if (! ctx->filename)
|
||||
{
|
||||
path = grub_strdup ("/");
|
||||
ctx->filename = pathname;
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx->filename++;
|
||||
path = grub_strdup (pathname);
|
||||
path[ctx->filename - pathname] = 0;
|
||||
}
|
||||
|
||||
/* It's the whole device. */
|
||||
if (! *pathname)
|
||||
{
|
||||
ctx->file_exists = 1;
|
||||
grub_memset (&ctx->file_info, 0, sizeof (ctx->file_info));
|
||||
/* Root is always a directory. */
|
||||
ctx->file_info.dir = 1;
|
||||
|
||||
/* Fetch writing time. */
|
||||
ctx->file_info.mtimeset = 0;
|
||||
if (fs->fs_mtime)
|
||||
{
|
||||
if (! fs->fs_mtime (dev, &ctx->file_info.mtime))
|
||||
ctx->file_info.mtimeset = 1;
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
}
|
||||
else
|
||||
(fs->fs_dir) (dev, path, find_file, ctx);
|
||||
|
||||
grub_device_close (dev);
|
||||
grub_free (path);
|
||||
grub_free (device_name);
|
||||
}
|
||||
|
||||
/* Parse a test expression starting from *argn. */
|
||||
static int
|
||||
test_parse (char **args, int *argn, int argc)
|
||||
{
|
||||
struct test_parse_ctx ctx = {
|
||||
.and = 1,
|
||||
.or = 0,
|
||||
.invert = 0
|
||||
};
|
||||
|
||||
/* Here we have the real parsing. */
|
||||
while (*argn < argc)
|
||||
{
|
||||
/* First try 3 argument tests. */
|
||||
if (*argn + 2 < argc)
|
||||
{
|
||||
/* String tests. */
|
||||
if (grub_strcmp (args[*argn + 1], "=") == 0
|
||||
|| grub_strcmp (args[*argn + 1], "==") == 0)
|
||||
{
|
||||
update_val (grub_strcmp (args[*argn], args[*argn + 2]) == 0,
|
||||
&ctx);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn + 1], "!=") == 0)
|
||||
{
|
||||
update_val (grub_strcmp (args[*argn], args[*argn + 2]) != 0,
|
||||
&ctx);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* GRUB extension: lexicographical sorting. */
|
||||
if (grub_strcmp (args[*argn + 1], "<") == 0)
|
||||
{
|
||||
update_val (grub_strcmp (args[*argn], args[*argn + 2]) < 0,
|
||||
&ctx);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn + 1], "<=") == 0)
|
||||
{
|
||||
update_val (grub_strcmp (args[*argn], args[*argn + 2]) <= 0,
|
||||
&ctx);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn + 1], ">") == 0)
|
||||
{
|
||||
update_val (grub_strcmp (args[*argn], args[*argn + 2]) > 0,
|
||||
&ctx);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn + 1], ">=") == 0)
|
||||
{
|
||||
update_val (grub_strcmp (args[*argn], args[*argn + 2]) >= 0,
|
||||
&ctx);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Number tests. */
|
||||
if (grub_strcmp (args[*argn + 1], "-eq") == 0)
|
||||
{
|
||||
update_val (grub_strtosl (args[*argn], 0, 0)
|
||||
== grub_strtosl (args[*argn + 2], 0, 0), &ctx);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn + 1], "-ge") == 0)
|
||||
{
|
||||
update_val (grub_strtosl (args[*argn], 0, 0)
|
||||
>= grub_strtosl (args[*argn + 2], 0, 0), &ctx);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn + 1], "-gt") == 0)
|
||||
{
|
||||
update_val (grub_strtosl (args[*argn], 0, 0)
|
||||
> grub_strtosl (args[*argn + 2], 0, 0), &ctx);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn + 1], "-le") == 0)
|
||||
{
|
||||
update_val (grub_strtosl (args[*argn], 0, 0)
|
||||
<= grub_strtosl (args[*argn + 2], 0, 0), &ctx);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn + 1], "-lt") == 0)
|
||||
{
|
||||
update_val (grub_strtosl (args[*argn], 0, 0)
|
||||
< grub_strtosl (args[*argn + 2], 0, 0), &ctx);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn + 1], "-ne") == 0)
|
||||
{
|
||||
update_val (grub_strtosl (args[*argn], 0, 0)
|
||||
!= grub_strtosl (args[*argn + 2], 0, 0), &ctx);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* GRUB extension: compare numbers skipping prefixes.
|
||||
Useful for comparing versions. E.g. vmlinuz-2 -plt vmlinuz-11. */
|
||||
if (grub_strcmp (args[*argn + 1], "-pgt") == 0
|
||||
|| grub_strcmp (args[*argn + 1], "-plt") == 0)
|
||||
{
|
||||
int i;
|
||||
/* Skip common prefix. */
|
||||
for (i = 0; args[*argn][i] == args[*argn + 2][i]
|
||||
&& args[*argn][i]; i++);
|
||||
|
||||
/* Go the digits back. */
|
||||
i--;
|
||||
while (grub_isdigit (args[*argn][i]) && i > 0)
|
||||
i--;
|
||||
i++;
|
||||
|
||||
if (grub_strcmp (args[*argn + 1], "-pgt") == 0)
|
||||
update_val (grub_strtoul (args[*argn] + i, 0, 0)
|
||||
> grub_strtoul (args[*argn + 2] + i, 0, 0), &ctx);
|
||||
else
|
||||
update_val (grub_strtoul (args[*argn] + i, 0, 0)
|
||||
< grub_strtoul (args[*argn + 2] + i, 0, 0), &ctx);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* -nt and -ot tests. GRUB extension: when doing -?t<bias> bias
|
||||
will be added to the first mtime. */
|
||||
if (grub_memcmp (args[*argn + 1], "-nt", 3) == 0
|
||||
|| grub_memcmp (args[*argn + 1], "-ot", 3) == 0)
|
||||
{
|
||||
struct grub_dirhook_info file1;
|
||||
int file1exists;
|
||||
int bias = 0;
|
||||
|
||||
/* Fetch fileinfo. */
|
||||
get_fileinfo (args[*argn], &ctx);
|
||||
file1 = ctx.file_info;
|
||||
file1exists = ctx.file_exists;
|
||||
get_fileinfo (args[*argn + 2], &ctx);
|
||||
|
||||
if (args[*argn + 1][3])
|
||||
bias = grub_strtosl (args[*argn + 1] + 3, 0, 0);
|
||||
|
||||
if (grub_memcmp (args[*argn + 1], "-nt", 3) == 0)
|
||||
update_val ((file1exists && ! ctx.file_exists)
|
||||
|| (file1.mtimeset && ctx.file_info.mtimeset
|
||||
&& file1.mtime + bias > ctx.file_info.mtime),
|
||||
&ctx);
|
||||
else
|
||||
update_val ((! file1exists && ctx.file_exists)
|
||||
|| (file1.mtimeset && ctx.file_info.mtimeset
|
||||
&& file1.mtime + bias < ctx.file_info.mtime),
|
||||
&ctx);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Two-argument tests. */
|
||||
if (*argn + 1 < argc)
|
||||
{
|
||||
/* File tests. */
|
||||
if (grub_strcmp (args[*argn], "-d") == 0)
|
||||
{
|
||||
get_fileinfo (args[*argn + 1], &ctx);
|
||||
update_val (ctx.file_exists && ctx.file_info.dir, &ctx);
|
||||
(*argn) += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn], "-D") == 0)
|
||||
{
|
||||
g_test_case_insensitive = 1;
|
||||
get_fileinfo (args[*argn + 1], &ctx);
|
||||
g_test_case_insensitive = 0;
|
||||
update_val (ctx.file_exists && ctx.file_info.dir, &ctx);
|
||||
(*argn) += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn], "-e") == 0)
|
||||
{
|
||||
get_fileinfo (args[*argn + 1], &ctx);
|
||||
update_val (ctx.file_exists, &ctx);
|
||||
(*argn) += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn], "-E") == 0)
|
||||
{
|
||||
g_test_case_insensitive = 1;
|
||||
get_fileinfo (args[*argn + 1], &ctx);
|
||||
g_test_case_insensitive = 0;
|
||||
update_val (ctx.file_exists, &ctx);
|
||||
(*argn) += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn], "-f") == 0)
|
||||
{
|
||||
get_fileinfo (args[*argn + 1], &ctx);
|
||||
/* FIXME: check for other types. */
|
||||
update_val (ctx.file_exists && ! ctx.file_info.dir, &ctx);
|
||||
(*argn) += 2;
|
||||
continue;
|
||||
}
|
||||
if (grub_strcmp (args[*argn], "-F") == 0)
|
||||
{
|
||||
g_test_case_insensitive = 1;
|
||||
get_fileinfo (args[*argn + 1], &ctx);
|
||||
g_test_case_insensitive = 0;
|
||||
/* FIXME: check for other types. */
|
||||
update_val (ctx.file_exists && ! ctx.file_info.dir, &ctx);
|
||||
(*argn) += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn], "-s") == 0)
|
||||
{
|
||||
grub_file_t file;
|
||||
file = grub_file_open (args[*argn + 1], GRUB_FILE_TYPE_GET_SIZE
|
||||
| GRUB_FILE_TYPE_NO_DECOMPRESS);
|
||||
update_val (file && (grub_file_size (file) != 0), &ctx);
|
||||
if (file)
|
||||
grub_file_close (file);
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
(*argn) += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* String tests. */
|
||||
if (grub_strcmp (args[*argn], "-n") == 0)
|
||||
{
|
||||
update_val (args[*argn + 1][0], &ctx);
|
||||
|
||||
(*argn) += 2;
|
||||
continue;
|
||||
}
|
||||
if (grub_strcmp (args[*argn], "-z") == 0)
|
||||
{
|
||||
update_val (! args[*argn + 1][0], &ctx);
|
||||
(*argn) += 2;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Special modifiers. */
|
||||
|
||||
/* End of expression. return to parent. */
|
||||
if (grub_strcmp (args[*argn], ")") == 0)
|
||||
{
|
||||
(*argn)++;
|
||||
return ctx.or || ctx.and;
|
||||
}
|
||||
/* Recursively invoke if parenthesis. */
|
||||
if (grub_strcmp (args[*argn], "(") == 0)
|
||||
{
|
||||
(*argn)++;
|
||||
update_val (test_parse (args, argn, argc), &ctx);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn], "!") == 0)
|
||||
{
|
||||
ctx.invert = ! ctx.invert;
|
||||
(*argn)++;
|
||||
continue;
|
||||
}
|
||||
if (grub_strcmp (args[*argn], "-a") == 0)
|
||||
{
|
||||
(*argn)++;
|
||||
continue;
|
||||
}
|
||||
if (grub_strcmp (args[*argn], "-o") == 0)
|
||||
{
|
||||
ctx.or = ctx.or || ctx.and;
|
||||
ctx.and = 1;
|
||||
(*argn)++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* No test found. Interpret if as just a string. */
|
||||
update_val (args[*argn][0], &ctx);
|
||||
(*argn)++;
|
||||
}
|
||||
return ctx.or || ctx.and;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_test (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
int argn = 0;
|
||||
|
||||
if (argc >= 1 && grub_strcmp (args[argc - 1], "]") == 0)
|
||||
argc--;
|
||||
|
||||
return test_parse (args, &argn, argc) ? GRUB_ERR_NONE
|
||||
: grub_error (GRUB_ERR_TEST_FAILURE, N_("false"));
|
||||
}
|
||||
|
||||
static grub_command_t cmd_1, cmd_2;
|
||||
|
||||
GRUB_MOD_INIT(test)
|
||||
{
|
||||
cmd_1 = grub_register_command ("[", grub_cmd_test,
|
||||
N_("EXPRESSION ]"), N_("Evaluate an expression."));
|
||||
cmd_1->flags |= GRUB_COMMAND_FLAG_EXTRACTOR;
|
||||
cmd_2 = grub_register_command ("test", grub_cmd_test,
|
||||
N_("EXPRESSION"), N_("Evaluate an expression."));
|
||||
cmd_2->flags |= GRUB_COMMAND_FLAG_EXTRACTOR;
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(test)
|
||||
{
|
||||
grub_unregister_command (cmd_1);
|
||||
grub_unregister_command (cmd_2);
|
||||
}
|
@@ -117,6 +117,8 @@ struct grub_fshelp_find_file_iter_ctx
|
||||
enum grub_fshelp_filetype *foundtype;
|
||||
};
|
||||
|
||||
int g_ventoy_case_insensitive = 0;
|
||||
|
||||
/* Helper for grub_fshelp_find_file. */
|
||||
static int
|
||||
find_file_iter (const char *filename, enum grub_fshelp_filetype filetype,
|
||||
@@ -124,6 +126,11 @@ find_file_iter (const char *filename, enum grub_fshelp_filetype filetype,
|
||||
{
|
||||
struct grub_fshelp_find_file_iter_ctx *ctx = data;
|
||||
|
||||
if (g_ventoy_case_insensitive)
|
||||
{
|
||||
filetype |= GRUB_FSHELP_CASE_INSENSITIVE;
|
||||
}
|
||||
|
||||
if (filetype == GRUB_FSHELP_UNKNOWN ||
|
||||
((filetype & GRUB_FSHELP_CASE_INSENSITIVE)
|
||||
? grub_strcasecmp (ctx->name, filename)
|
||||
|
@@ -32,6 +32,7 @@
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static int g_ventoy_no_joliet = 0;
|
||||
static grub_uint64_t g_ventoy_last_read_pos = 0;
|
||||
static grub_uint64_t g_ventoy_last_read_offset = 0;
|
||||
static grub_uint64_t g_ventoy_last_read_dirent_pos = 0;
|
||||
@@ -480,8 +481,10 @@ grub_iso9660_mount (grub_disk_t disk)
|
||||
(voldesc.escape[2] == 0x43) || /* UCS-2 Level 2. */
|
||||
(voldesc.escape[2] == 0x45))) /* UCS-2 Level 3. */
|
||||
{
|
||||
copy_voldesc = 1;
|
||||
data->joliet = 1;
|
||||
if (0 == g_ventoy_no_joliet) {
|
||||
copy_voldesc = 1;
|
||||
data->joliet = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (copy_voldesc)
|
||||
@@ -1108,6 +1111,11 @@ grub_iso9660_mtime (grub_device_t device, grub_int32_t *timebuf)
|
||||
return err;
|
||||
}
|
||||
|
||||
void grub_iso9660_set_nojoliet(int nojoliet)
|
||||
{
|
||||
g_ventoy_no_joliet = nojoliet;
|
||||
}
|
||||
|
||||
grub_uint64_t grub_iso9660_get_last_read_pos(grub_file_t file)
|
||||
{
|
||||
(void)file;
|
||||
|
839
GRUB2/MOD_SRC/grub-2.04/grub-core/gfxmenu/theme_loader.c
Normal file
@@ -0,0 +1,839 @@
|
||||
/* theme_loader.c - Theme file loader for gfxmenu. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/types.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/video.h>
|
||||
#include <grub/gui_string_util.h>
|
||||
#include <grub/bitmap.h>
|
||||
#include <grub/bitmap_scale.h>
|
||||
#include <grub/gfxwidgets.h>
|
||||
#include <grub/gfxmenu_view.h>
|
||||
#include <grub/gui.h>
|
||||
#include <grub/color.h>
|
||||
#include <grub/env.h>
|
||||
|
||||
static grub_err_t
|
||||
parse_proportional_spec (const char *value, signed *abs, grub_fixed_signed_t *prop);
|
||||
|
||||
/* Construct a new box widget using ABSPATTERN to find the pixmap files for
|
||||
it, storing the new box instance at *BOXPTR.
|
||||
PATTERN should be of the form: "(hd0,0)/somewhere/style*.png".
|
||||
The '*' then gets substituted with the various pixmap names that the
|
||||
box uses. */
|
||||
static grub_err_t
|
||||
recreate_box_absolute (grub_gfxmenu_box_t *boxptr, const char *abspattern)
|
||||
{
|
||||
char *prefix;
|
||||
char *suffix;
|
||||
char *star;
|
||||
grub_gfxmenu_box_t box;
|
||||
|
||||
star = grub_strchr (abspattern, '*');
|
||||
if (! star)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"missing `*' in box pixmap pattern `%s'", abspattern);
|
||||
|
||||
/* Prefix: Get the part before the '*'. */
|
||||
prefix = grub_malloc (star - abspattern + 1);
|
||||
if (! prefix)
|
||||
return grub_errno;
|
||||
|
||||
grub_memcpy (prefix, abspattern, star - abspattern);
|
||||
prefix[star - abspattern] = '\0';
|
||||
|
||||
/* Suffix: Everything after the '*' is the suffix. */
|
||||
suffix = star + 1;
|
||||
|
||||
box = grub_gfxmenu_create_box (prefix, suffix);
|
||||
grub_free (prefix);
|
||||
if (! box)
|
||||
return grub_errno;
|
||||
|
||||
if (*boxptr)
|
||||
(*boxptr)->destroy (*boxptr);
|
||||
*boxptr = box;
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
|
||||
/* Construct a new box widget using PATTERN to find the pixmap files for it,
|
||||
storing the new widget at *BOXPTR. PATTERN should be of the form:
|
||||
"somewhere/style*.png". The '*' then gets substituted with the various
|
||||
pixmap names that the widget uses.
|
||||
|
||||
Important! The value of *BOXPTR must be initialized! It must either
|
||||
(1) Be 0 (a NULL pointer), or
|
||||
(2) Be a pointer to a valid 'grub_gfxmenu_box_t' instance.
|
||||
In this case, the previous instance is destroyed. */
|
||||
grub_err_t
|
||||
grub_gui_recreate_box (grub_gfxmenu_box_t *boxptr,
|
||||
const char *pattern, const char *theme_dir)
|
||||
{
|
||||
char *abspattern;
|
||||
|
||||
/* Check arguments. */
|
||||
if (! pattern)
|
||||
{
|
||||
/* If no pixmap pattern is given, then just create an empty box. */
|
||||
if (*boxptr)
|
||||
(*boxptr)->destroy (*boxptr);
|
||||
*boxptr = grub_gfxmenu_create_box (0, 0);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
if (! theme_dir)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"styled box missing theme directory");
|
||||
|
||||
/* Resolve to an absolute path. */
|
||||
abspattern = grub_resolve_relative_path (theme_dir, pattern);
|
||||
if (! abspattern)
|
||||
return grub_errno;
|
||||
|
||||
/* Create the box. */
|
||||
recreate_box_absolute (boxptr, abspattern);
|
||||
grub_free (abspattern);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
theme_get_unsigned_int_from_proportional (const char *value,
|
||||
unsigned absolute_value,
|
||||
unsigned int *parsed_value)
|
||||
{
|
||||
grub_err_t err;
|
||||
grub_fixed_signed_t frac;
|
||||
signed pixels;
|
||||
err = parse_proportional_spec (value, &pixels, &frac);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
int result = grub_fixed_sfs_multiply (absolute_value, frac) + pixels;
|
||||
if (result < 0)
|
||||
result = 0;
|
||||
*parsed_value = result;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
/* Set the specified property NAME on the view to the given string VALUE.
|
||||
The caller is responsible for the lifetimes of NAME and VALUE. */
|
||||
static grub_err_t
|
||||
theme_set_string (grub_gfxmenu_view_t view,
|
||||
const char *name,
|
||||
const char *value,
|
||||
const char *theme_dir,
|
||||
const char *filename,
|
||||
int line_num,
|
||||
int col_num)
|
||||
{
|
||||
if (! grub_strcmp ("title-font", name))
|
||||
view->title_font = grub_font_get (value);
|
||||
else if (! grub_strcmp ("message-font", name))
|
||||
view->message_font = grub_font_get (value);
|
||||
else if (! grub_strcmp ("terminal-font", name))
|
||||
{
|
||||
grub_free (view->terminal_font_name);
|
||||
view->terminal_font_name = grub_strdup (value);
|
||||
if (! view->terminal_font_name)
|
||||
return grub_errno;
|
||||
}
|
||||
else if (! grub_strcmp ("title-color", name))
|
||||
grub_video_parse_color (value, &view->title_color);
|
||||
else if (! grub_strcmp ("message-color", name))
|
||||
grub_video_parse_color (value, &view->message_color);
|
||||
else if (! grub_strcmp ("message-bg-color", name))
|
||||
grub_video_parse_color (value, &view->message_bg_color);
|
||||
else if (! grub_strcmp ("desktop-image", name))
|
||||
{
|
||||
struct grub_video_bitmap *raw_bitmap;
|
||||
char *path;
|
||||
path = grub_resolve_relative_path (theme_dir, value);
|
||||
if (! path)
|
||||
return grub_errno;
|
||||
if (grub_video_bitmap_load (&raw_bitmap, path) != GRUB_ERR_NONE)
|
||||
{
|
||||
grub_free (path);
|
||||
return grub_errno;
|
||||
}
|
||||
grub_free(path);
|
||||
grub_video_bitmap_destroy (view->raw_desktop_image);
|
||||
view->raw_desktop_image = raw_bitmap;
|
||||
}
|
||||
else if (! grub_strcmp ("desktop-image-scale-method", name))
|
||||
{
|
||||
if (! value || ! grub_strcmp ("stretch", value))
|
||||
view->desktop_image_scale_method =
|
||||
GRUB_VIDEO_BITMAP_SELECTION_METHOD_STRETCH;
|
||||
else if (! grub_strcmp ("crop", value))
|
||||
view->desktop_image_scale_method =
|
||||
GRUB_VIDEO_BITMAP_SELECTION_METHOD_CROP;
|
||||
else if (! grub_strcmp ("padding", value))
|
||||
view->desktop_image_scale_method =
|
||||
GRUB_VIDEO_BITMAP_SELECTION_METHOD_PADDING;
|
||||
else if (! grub_strcmp ("fitwidth", value))
|
||||
view->desktop_image_scale_method =
|
||||
GRUB_VIDEO_BITMAP_SELECTION_METHOD_FITWIDTH;
|
||||
else if (! grub_strcmp ("fitheight", value))
|
||||
view->desktop_image_scale_method =
|
||||
GRUB_VIDEO_BITMAP_SELECTION_METHOD_FITHEIGHT;
|
||||
else
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"Unsupported scale method: %s",
|
||||
value);
|
||||
}
|
||||
else if (! grub_strcmp ("desktop-image-h-align", name))
|
||||
{
|
||||
if (! grub_strcmp ("left", value))
|
||||
view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_LEFT;
|
||||
else if (! grub_strcmp ("center", value))
|
||||
view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_CENTER;
|
||||
else if (! grub_strcmp ("right", value))
|
||||
view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_RIGHT;
|
||||
else
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"Unsupported horizontal align method: %s",
|
||||
value);
|
||||
}
|
||||
else if (! grub_strcmp ("desktop-image-v-align", name))
|
||||
{
|
||||
if (! grub_strcmp ("top", value))
|
||||
view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_TOP;
|
||||
else if (! grub_strcmp ("center", value))
|
||||
view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_CENTER;
|
||||
else if (! grub_strcmp ("bottom", value))
|
||||
view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_BOTTOM;
|
||||
else
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"Unsupported vertical align method: %s",
|
||||
value);
|
||||
}
|
||||
else if (! grub_strcmp ("desktop-color", name))
|
||||
grub_video_parse_color (value, &view->desktop_color);
|
||||
else if (! grub_strcmp ("terminal-box", name))
|
||||
{
|
||||
grub_err_t err;
|
||||
err = grub_gui_recreate_box (&view->terminal_box, value, theme_dir);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
}
|
||||
else if (! grub_strcmp ("terminal-border", name))
|
||||
{
|
||||
view->terminal_border = grub_strtoul (value, 0, 10);
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
}
|
||||
else if (! grub_strcmp ("terminal-left", name))
|
||||
{
|
||||
unsigned int tmp;
|
||||
int err = theme_get_unsigned_int_from_proportional (value,
|
||||
view->screen.width,
|
||||
&tmp);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
view->terminal_rect.x = tmp;
|
||||
}
|
||||
else if (! grub_strcmp ("terminal-top", name))
|
||||
{
|
||||
unsigned int tmp;
|
||||
int err = theme_get_unsigned_int_from_proportional (value,
|
||||
view->screen.height,
|
||||
&tmp);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
view->terminal_rect.y = tmp;
|
||||
}
|
||||
else if (! grub_strcmp ("terminal-width", name))
|
||||
{
|
||||
unsigned int tmp;
|
||||
int err = theme_get_unsigned_int_from_proportional (value,
|
||||
view->screen.width,
|
||||
&tmp);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
view->terminal_rect.width = tmp;
|
||||
}
|
||||
else if (! grub_strcmp ("terminal-height", name))
|
||||
{
|
||||
unsigned int tmp;
|
||||
int err = theme_get_unsigned_int_from_proportional (value,
|
||||
view->screen.height,
|
||||
&tmp);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
view->terminal_rect.height = tmp;
|
||||
}
|
||||
else if (! grub_strcmp ("title-text", name))
|
||||
{
|
||||
grub_free (view->title_text);
|
||||
view->title_text = grub_strdup (value);
|
||||
if (! view->title_text)
|
||||
return grub_errno;
|
||||
}
|
||||
else
|
||||
{
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"%s:%d:%d unknown property `%s'",
|
||||
filename, line_num, col_num, name);
|
||||
}
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
struct parsebuf
|
||||
{
|
||||
char *buf;
|
||||
int pos;
|
||||
int len;
|
||||
int line_num;
|
||||
int col_num;
|
||||
const char *filename;
|
||||
char *theme_dir;
|
||||
grub_gfxmenu_view_t view;
|
||||
};
|
||||
|
||||
static int
|
||||
has_more (struct parsebuf *p)
|
||||
{
|
||||
return p->pos < p->len;
|
||||
}
|
||||
|
||||
static int
|
||||
read_char (struct parsebuf *p)
|
||||
{
|
||||
if (has_more (p))
|
||||
{
|
||||
char c;
|
||||
c = p->buf[p->pos++];
|
||||
if (c == '\n')
|
||||
{
|
||||
p->line_num++;
|
||||
p->col_num = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
p->col_num++;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
peek_char (struct parsebuf *p)
|
||||
{
|
||||
if (has_more (p))
|
||||
return p->buf[p->pos];
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
is_whitespace (char c)
|
||||
{
|
||||
return (c == ' '
|
||||
|| c == '\t'
|
||||
|| c == '\r'
|
||||
|| c == '\n'
|
||||
|| c == '\f');
|
||||
}
|
||||
|
||||
static void
|
||||
skip_whitespace (struct parsebuf *p)
|
||||
{
|
||||
while (has_more (p) && is_whitespace(peek_char (p)))
|
||||
read_char (p);
|
||||
}
|
||||
|
||||
static void
|
||||
advance_to_next_line (struct parsebuf *p)
|
||||
{
|
||||
int c;
|
||||
|
||||
/* Eat characters up to the newline. */
|
||||
do
|
||||
{
|
||||
c = read_char (p);
|
||||
}
|
||||
while (c != -1 && c != '\n');
|
||||
}
|
||||
|
||||
static int
|
||||
is_identifier_char (int c)
|
||||
{
|
||||
return (c != -1
|
||||
&& (grub_isalpha(c)
|
||||
|| grub_isdigit(c)
|
||||
|| c == '_'
|
||||
|| c == '-'));
|
||||
}
|
||||
|
||||
static char *
|
||||
read_identifier (struct parsebuf *p)
|
||||
{
|
||||
/* Index of the first character of the identifier in p->buf. */
|
||||
int start;
|
||||
/* Next index after the last character of the identifer in p->buf. */
|
||||
int end;
|
||||
|
||||
skip_whitespace (p);
|
||||
|
||||
/* Capture the start of the identifier. */
|
||||
start = p->pos;
|
||||
|
||||
/* Scan for the end. */
|
||||
while (is_identifier_char (peek_char (p)))
|
||||
read_char (p);
|
||||
end = p->pos;
|
||||
|
||||
if (end - start < 1)
|
||||
return 0;
|
||||
|
||||
return grub_new_substring (p->buf, start, end);
|
||||
}
|
||||
|
||||
static char *
|
||||
read_expression (struct parsebuf *p)
|
||||
{
|
||||
int start;
|
||||
int end;
|
||||
|
||||
skip_whitespace (p);
|
||||
if (peek_char (p) == '"')
|
||||
{
|
||||
/* Read as a quoted string.
|
||||
The quotation marks are not included in the expression value. */
|
||||
/* Skip opening quotation mark. */
|
||||
read_char (p);
|
||||
start = p->pos;
|
||||
while (has_more (p) && peek_char (p) != '"')
|
||||
read_char (p);
|
||||
end = p->pos;
|
||||
/* Skip the terminating quotation mark. */
|
||||
read_char (p);
|
||||
}
|
||||
else if (peek_char (p) == '(')
|
||||
{
|
||||
/* Read as a parenthesized string -- for tuples/coordinates. */
|
||||
/* The parentheses are included in the expression value. */
|
||||
int c;
|
||||
|
||||
start = p->pos;
|
||||
do
|
||||
{
|
||||
c = read_char (p);
|
||||
}
|
||||
while (c != -1 && c != ')');
|
||||
end = p->pos;
|
||||
}
|
||||
else if (has_more (p))
|
||||
{
|
||||
/* Read as a single word -- for numeric values or words without
|
||||
whitespace. */
|
||||
start = p->pos;
|
||||
while (has_more (p) && ! is_whitespace (peek_char (p)))
|
||||
read_char (p);
|
||||
end = p->pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The end of the theme file has been reached. */
|
||||
grub_error (GRUB_ERR_IO, "%s:%d:%d expression expected in theme file",
|
||||
p->filename, p->line_num, p->col_num);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return grub_new_substring (p->buf, start, end);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
parse_proportional_spec (const char *value, signed *abs, grub_fixed_signed_t *prop)
|
||||
{
|
||||
signed num;
|
||||
const char *ptr;
|
||||
int sig = 0;
|
||||
*abs = 0;
|
||||
*prop = 0;
|
||||
ptr = value;
|
||||
while (*ptr)
|
||||
{
|
||||
sig = 0;
|
||||
|
||||
while (*ptr == '-' || *ptr == '+')
|
||||
{
|
||||
if (*ptr == '-')
|
||||
sig = !sig;
|
||||
ptr++;
|
||||
}
|
||||
|
||||
num = grub_strtoul (ptr, (char **) &ptr, 0);
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
if (sig)
|
||||
num = -num;
|
||||
if (*ptr == '%')
|
||||
{
|
||||
*prop += grub_fixed_fsf_divide (grub_signed_to_fixed (num), 100);
|
||||
ptr++;
|
||||
}
|
||||
else
|
||||
*abs += num;
|
||||
}
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
|
||||
/* Read a GUI object specification from the theme file.
|
||||
Any components created will be added to the GUI container PARENT. */
|
||||
static grub_err_t
|
||||
read_object (struct parsebuf *p, grub_gui_container_t parent)
|
||||
{
|
||||
grub_video_rect_t bounds;
|
||||
|
||||
char *name;
|
||||
name = read_identifier (p);
|
||||
if (! name)
|
||||
goto cleanup;
|
||||
|
||||
grub_gui_component_t component = 0;
|
||||
if (grub_strcmp (name, "label") == 0)
|
||||
{
|
||||
component = grub_gui_label_new ();
|
||||
}
|
||||
else if (grub_strcmp (name, "image") == 0)
|
||||
{
|
||||
component = grub_gui_image_new ();
|
||||
}
|
||||
else if (grub_strcmp (name, "vbox") == 0)
|
||||
{
|
||||
component = (grub_gui_component_t) grub_gui_vbox_new ();
|
||||
}
|
||||
else if (grub_strcmp (name, "hbox") == 0)
|
||||
{
|
||||
component = (grub_gui_component_t) grub_gui_hbox_new ();
|
||||
}
|
||||
else if (grub_strcmp (name, "canvas") == 0)
|
||||
{
|
||||
component = (grub_gui_component_t) grub_gui_canvas_new ();
|
||||
}
|
||||
else if (grub_strcmp (name, "progress_bar") == 0)
|
||||
{
|
||||
component = grub_gui_progress_bar_new ();
|
||||
}
|
||||
else if (grub_strcmp (name, "circular_progress") == 0)
|
||||
{
|
||||
component = grub_gui_circular_progress_new ();
|
||||
}
|
||||
else if (grub_strcmp (name, "boot_menu") == 0)
|
||||
{
|
||||
component = grub_gui_list_new ();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unknown type. */
|
||||
grub_error (GRUB_ERR_IO, "%s:%d:%d unknown object type `%s'",
|
||||
p->filename, p->line_num, p->col_num, name);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (! component)
|
||||
goto cleanup;
|
||||
|
||||
/* Inform the component about the theme so it can find its resources. */
|
||||
component->ops->set_property (component, "theme_dir", p->theme_dir);
|
||||
component->ops->set_property (component, "theme_path", p->filename);
|
||||
|
||||
/* Add the component as a child of PARENT. */
|
||||
bounds.x = 0;
|
||||
bounds.y = 0;
|
||||
bounds.width = -1;
|
||||
bounds.height = -1;
|
||||
component->ops->set_bounds (component, &bounds);
|
||||
parent->ops->add (parent, component);
|
||||
|
||||
skip_whitespace (p);
|
||||
if (read_char (p) != '{')
|
||||
{
|
||||
grub_error (GRUB_ERR_IO,
|
||||
"%s:%d:%d expected `{' after object type name `%s'",
|
||||
p->filename, p->line_num, p->col_num, name);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
while (has_more (p))
|
||||
{
|
||||
skip_whitespace (p);
|
||||
|
||||
/* Check whether the end has been encountered. */
|
||||
if (peek_char (p) == '}')
|
||||
{
|
||||
/* Skip the closing brace. */
|
||||
read_char (p);
|
||||
break;
|
||||
}
|
||||
|
||||
if (peek_char (p) == '#')
|
||||
{
|
||||
/* Skip comments. */
|
||||
advance_to_next_line (p);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (peek_char (p) == '+')
|
||||
{
|
||||
/* Skip the '+'. */
|
||||
read_char (p);
|
||||
|
||||
/* Check whether this component is a container. */
|
||||
if (component->ops->is_instance (component, "container"))
|
||||
{
|
||||
/* Read the sub-object recursively and add it as a child. */
|
||||
if (read_object (p, (grub_gui_container_t) component) != 0)
|
||||
goto cleanup;
|
||||
/* After reading the sub-object, resume parsing, expecting
|
||||
another property assignment or sub-object definition. */
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_error (GRUB_ERR_IO,
|
||||
"%s:%d:%d attempted to add object to non-container",
|
||||
p->filename, p->line_num, p->col_num);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
char *property;
|
||||
property = read_identifier (p);
|
||||
if (! property)
|
||||
{
|
||||
grub_error (GRUB_ERR_IO, "%s:%d:%d identifier expected in theme file",
|
||||
p->filename, p->line_num, p->col_num);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
skip_whitespace (p);
|
||||
if (read_char (p) != '=')
|
||||
{
|
||||
grub_error (GRUB_ERR_IO,
|
||||
"%s:%d:%d expected `=' after property name `%s'",
|
||||
p->filename, p->line_num, p->col_num, property);
|
||||
grub_free (property);
|
||||
goto cleanup;
|
||||
}
|
||||
skip_whitespace (p);
|
||||
|
||||
char *value;
|
||||
value = read_expression (p);
|
||||
if (! value)
|
||||
{
|
||||
grub_free (property);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Handle the property value. */
|
||||
if (grub_strcmp (property, "left") == 0)
|
||||
parse_proportional_spec (value, &component->x, &component->xfrac);
|
||||
else if (grub_strcmp (property, "top") == 0)
|
||||
parse_proportional_spec (value, &component->y, &component->yfrac);
|
||||
else if (grub_strcmp (property, "width") == 0)
|
||||
parse_proportional_spec (value, &component->w, &component->wfrac);
|
||||
else if (grub_strcmp (property, "height") == 0)
|
||||
parse_proportional_spec (value, &component->h, &component->hfrac);
|
||||
else
|
||||
/* General property handling. */
|
||||
component->ops->set_property (component, property, value);
|
||||
|
||||
grub_free (value);
|
||||
grub_free (property);
|
||||
if (grub_errno != GRUB_ERR_NONE)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
grub_free (name);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
read_property (struct parsebuf *p)
|
||||
{
|
||||
char *name;
|
||||
|
||||
/* Read the property name. */
|
||||
name = read_identifier (p);
|
||||
if (! name)
|
||||
{
|
||||
advance_to_next_line (p);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
/* Skip whitespace before separator. */
|
||||
skip_whitespace (p);
|
||||
|
||||
/* Read separator. */
|
||||
if (read_char (p) != ':')
|
||||
{
|
||||
grub_error (GRUB_ERR_IO,
|
||||
"%s:%d:%d missing separator after property name `%s'",
|
||||
p->filename, p->line_num, p->col_num, name);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Skip whitespace after separator. */
|
||||
skip_whitespace (p);
|
||||
|
||||
/* Get the value based on its type. */
|
||||
if (peek_char (p) == '"')
|
||||
{
|
||||
/* String value (e.g., '"My string"'). */
|
||||
char *value = read_expression (p);
|
||||
if (! value)
|
||||
{
|
||||
grub_error (GRUB_ERR_IO, "%s:%d:%d missing property value",
|
||||
p->filename, p->line_num, p->col_num);
|
||||
goto done;
|
||||
}
|
||||
/* If theme_set_string results in an error, grub_errno will be returned
|
||||
below. */
|
||||
theme_set_string (p->view, name, value, p->theme_dir,
|
||||
p->filename, p->line_num, p->col_num);
|
||||
grub_free (value);
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_error (GRUB_ERR_IO,
|
||||
"%s:%d:%d property value invalid; "
|
||||
"enclose literal values in quotes (\")",
|
||||
p->filename, p->line_num, p->col_num);
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
grub_free (name);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
/* Set properties on the view based on settings from the specified
|
||||
theme file. */
|
||||
grub_err_t
|
||||
grub_gfxmenu_view_load_theme (grub_gfxmenu_view_t view, const char *theme_path)
|
||||
{
|
||||
grub_file_t file;
|
||||
struct parsebuf p;
|
||||
|
||||
p.view = view;
|
||||
p.theme_dir = grub_get_dirname (theme_path);
|
||||
|
||||
file = grub_file_open (theme_path, GRUB_FILE_TYPE_THEME);
|
||||
if (! file)
|
||||
{
|
||||
grub_free (p.theme_dir);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
p.len = grub_file_size (file);
|
||||
p.buf = grub_malloc (p.len + 4096);
|
||||
p.pos = 0;
|
||||
p.line_num = 1;
|
||||
p.col_num = 1;
|
||||
p.filename = theme_path;
|
||||
if (! p.buf)
|
||||
{
|
||||
grub_file_close (file);
|
||||
grub_free (p.theme_dir);
|
||||
return grub_errno;
|
||||
}
|
||||
if (grub_file_read (file, p.buf, p.len) != p.len)
|
||||
{
|
||||
grub_free (p.buf);
|
||||
grub_file_close (file);
|
||||
grub_free (p.theme_dir);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
{
|
||||
const char *checkret = grub_env_get("VTOY_CHKDEV_RESULT_STRING");
|
||||
if (checkret == NULL || checkret[0] != '0')
|
||||
{
|
||||
p.len += grub_snprintf(p.buf + p.len, 4096, "\n+ hbox{\n left = 1%%\n top = 90%%\n"
|
||||
" + label {text = \"[Unofficial Ventoy]\" color = \"red\" align = \"left\"}\n"
|
||||
"}\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (view->canvas)
|
||||
view->canvas->component.ops->destroy (view->canvas);
|
||||
|
||||
view->canvas = grub_gui_canvas_new ();
|
||||
if (!view->canvas)
|
||||
goto fail;
|
||||
((grub_gui_component_t) view->canvas)
|
||||
->ops->set_bounds ((grub_gui_component_t) view->canvas,
|
||||
&view->screen);
|
||||
|
||||
while (has_more (&p))
|
||||
{
|
||||
/* Skip comments (lines beginning with #). */
|
||||
if (peek_char (&p) == '#')
|
||||
{
|
||||
advance_to_next_line (&p);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Find the first non-whitespace character. */
|
||||
skip_whitespace (&p);
|
||||
|
||||
/* Handle the content. */
|
||||
if (peek_char (&p) == '+')
|
||||
{
|
||||
/* Skip the '+'. */
|
||||
read_char (&p);
|
||||
read_object (&p, view->canvas);
|
||||
}
|
||||
else
|
||||
{
|
||||
read_property (&p);
|
||||
}
|
||||
|
||||
if (grub_errno != GRUB_ERR_NONE)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Set the new theme path. */
|
||||
grub_free (view->theme_path);
|
||||
view->theme_path = grub_strdup (theme_path);
|
||||
goto cleanup;
|
||||
|
||||
fail:
|
||||
if (view->canvas)
|
||||
{
|
||||
view->canvas->component.ops->destroy (view->canvas);
|
||||
view->canvas = 0;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
grub_free (p.buf);
|
||||
grub_file_close (file);
|
||||
grub_free (p.theme_dir);
|
||||
return grub_errno;
|
||||
}
|
647
GRUB2/MOD_SRC/grub-2.04/grub-core/gfxmenu/view.c
Normal file
@@ -0,0 +1,647 @@
|
||||
/* view.c - Graphical menu interface MVC view. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/types.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/video.h>
|
||||
#include <grub/gfxterm.h>
|
||||
#include <grub/bitmap.h>
|
||||
#include <grub/bitmap_scale.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/gfxwidgets.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/menu.h>
|
||||
#include <grub/menu_viewer.h>
|
||||
#include <grub/gfxmenu_view.h>
|
||||
#include <grub/gui_string_util.h>
|
||||
#include <grub/icon_manager.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static void
|
||||
init_terminal (grub_gfxmenu_view_t view);
|
||||
static void
|
||||
init_background (grub_gfxmenu_view_t view);
|
||||
static grub_gfxmenu_view_t term_view;
|
||||
|
||||
/* Create a new view object, loading the theme specified by THEME_PATH and
|
||||
associating MODEL with the view. */
|
||||
grub_gfxmenu_view_t
|
||||
grub_gfxmenu_view_new (const char *theme_path,
|
||||
int width, int height)
|
||||
{
|
||||
grub_gfxmenu_view_t view;
|
||||
grub_font_t default_font;
|
||||
grub_video_rgba_color_t default_fg_color;
|
||||
grub_video_rgba_color_t default_bg_color;
|
||||
|
||||
view = grub_malloc (sizeof (*view));
|
||||
if (! view)
|
||||
return 0;
|
||||
|
||||
while (grub_gfxmenu_timeout_notifications)
|
||||
{
|
||||
struct grub_gfxmenu_timeout_notify *p;
|
||||
p = grub_gfxmenu_timeout_notifications;
|
||||
grub_gfxmenu_timeout_notifications = grub_gfxmenu_timeout_notifications->next;
|
||||
grub_free (p);
|
||||
}
|
||||
|
||||
view->screen.x = 0;
|
||||
view->screen.y = 0;
|
||||
view->screen.width = width;
|
||||
view->screen.height = height;
|
||||
|
||||
view->need_to_check_sanity = 1;
|
||||
view->terminal_border = 3;
|
||||
view->terminal_rect.width = view->screen.width * 7 / 10;
|
||||
view->terminal_rect.height = view->screen.height * 7 / 10;
|
||||
view->terminal_rect.x = view->screen.x + (view->screen.width
|
||||
- view->terminal_rect.width) / 2;
|
||||
view->terminal_rect.y = view->screen.y + (view->screen.height
|
||||
- view->terminal_rect.height) / 2;
|
||||
|
||||
default_font = grub_font_get ("Unknown Regular 16");
|
||||
default_fg_color = grub_video_rgba_color_rgb (0, 0, 0);
|
||||
default_bg_color = grub_video_rgba_color_rgb (255, 255, 255);
|
||||
|
||||
view->canvas = 0;
|
||||
|
||||
view->title_font = default_font;
|
||||
view->message_font = default_font;
|
||||
view->terminal_font_name = grub_strdup ("Fixed 10");
|
||||
view->title_color = default_fg_color;
|
||||
view->message_color = default_bg_color;
|
||||
view->message_bg_color = default_fg_color;
|
||||
view->raw_desktop_image = 0;
|
||||
view->scaled_desktop_image = 0;
|
||||
view->desktop_image_scale_method = GRUB_VIDEO_BITMAP_SELECTION_METHOD_STRETCH;
|
||||
view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_CENTER;
|
||||
view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_CENTER;
|
||||
view->desktop_color = default_bg_color;
|
||||
view->terminal_box = grub_gfxmenu_create_box (0, 0);
|
||||
view->title_text = grub_strdup (_("GRUB Boot Menu"));
|
||||
view->progress_message_text = 0;
|
||||
view->theme_path = 0;
|
||||
|
||||
/* Set the timeout bar's frame. */
|
||||
view->progress_message_frame.width = view->screen.width * 4 / 5;
|
||||
view->progress_message_frame.height = 50;
|
||||
view->progress_message_frame.x = view->screen.x
|
||||
+ (view->screen.width - view->progress_message_frame.width) / 2;
|
||||
view->progress_message_frame.y = view->screen.y
|
||||
+ view->screen.height - 90 - 20 - view->progress_message_frame.height;
|
||||
|
||||
if (grub_gfxmenu_view_load_theme (view, theme_path) != 0)
|
||||
{
|
||||
grub_gfxmenu_view_destroy (view);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
/* Destroy the view object. All used memory is freed. */
|
||||
void
|
||||
grub_gfxmenu_view_destroy (grub_gfxmenu_view_t view)
|
||||
{
|
||||
if (!view)
|
||||
return;
|
||||
while (grub_gfxmenu_timeout_notifications)
|
||||
{
|
||||
struct grub_gfxmenu_timeout_notify *p;
|
||||
p = grub_gfxmenu_timeout_notifications;
|
||||
grub_gfxmenu_timeout_notifications = grub_gfxmenu_timeout_notifications->next;
|
||||
grub_free (p);
|
||||
}
|
||||
grub_video_bitmap_destroy (view->raw_desktop_image);
|
||||
grub_video_bitmap_destroy (view->scaled_desktop_image);
|
||||
if (view->terminal_box)
|
||||
view->terminal_box->destroy (view->terminal_box);
|
||||
grub_free (view->terminal_font_name);
|
||||
grub_free (view->title_text);
|
||||
grub_free (view->progress_message_text);
|
||||
grub_free (view->theme_path);
|
||||
if (view->canvas)
|
||||
view->canvas->component.ops->destroy (view->canvas);
|
||||
grub_free (view);
|
||||
}
|
||||
|
||||
static void
|
||||
redraw_background (grub_gfxmenu_view_t view,
|
||||
const grub_video_rect_t *bounds)
|
||||
{
|
||||
if (view->scaled_desktop_image)
|
||||
{
|
||||
struct grub_video_bitmap *img = view->scaled_desktop_image;
|
||||
grub_video_blit_bitmap (img, GRUB_VIDEO_BLIT_REPLACE,
|
||||
bounds->x, bounds->y,
|
||||
bounds->x - view->screen.x,
|
||||
bounds->y - view->screen.y,
|
||||
bounds->width, bounds->height);
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_video_fill_rect (grub_video_map_rgba_color (view->desktop_color),
|
||||
bounds->x, bounds->y,
|
||||
bounds->width, bounds->height);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
draw_title (grub_gfxmenu_view_t view)
|
||||
{
|
||||
if (! view->title_text)
|
||||
return;
|
||||
|
||||
/* Center the title. */
|
||||
int title_width = grub_font_get_string_width (view->title_font,
|
||||
view->title_text);
|
||||
int x = (view->screen.width - title_width) / 2;
|
||||
int y = 40 + grub_font_get_ascent (view->title_font);
|
||||
grub_font_draw_string (view->title_text,
|
||||
view->title_font,
|
||||
grub_video_map_rgba_color (view->title_color),
|
||||
x, y);
|
||||
}
|
||||
|
||||
struct progress_value_data
|
||||
{
|
||||
int visible;
|
||||
int start;
|
||||
int end;
|
||||
int value;
|
||||
};
|
||||
|
||||
struct grub_gfxmenu_timeout_notify *grub_gfxmenu_timeout_notifications;
|
||||
|
||||
static void
|
||||
update_timeouts (int visible, int start, int value, int end)
|
||||
{
|
||||
struct grub_gfxmenu_timeout_notify *cur;
|
||||
|
||||
for (cur = grub_gfxmenu_timeout_notifications; cur; cur = cur->next)
|
||||
cur->set_state (cur->self, visible, start, value, end);
|
||||
}
|
||||
|
||||
static void
|
||||
redraw_timeouts (struct grub_gfxmenu_view *view)
|
||||
{
|
||||
struct grub_gfxmenu_timeout_notify *cur;
|
||||
|
||||
for (cur = grub_gfxmenu_timeout_notifications; cur; cur = cur->next)
|
||||
{
|
||||
grub_video_rect_t bounds;
|
||||
cur->self->ops->get_bounds (cur->self, &bounds);
|
||||
grub_video_set_area_status (GRUB_VIDEO_AREA_ENABLED);
|
||||
grub_gfxmenu_view_redraw (view, &bounds);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
grub_gfxmenu_print_timeout (int timeout, void *data)
|
||||
{
|
||||
struct grub_gfxmenu_view *view = data;
|
||||
|
||||
if (view->first_timeout == -1)
|
||||
view->first_timeout = timeout;
|
||||
|
||||
update_timeouts (1, -view->first_timeout, -timeout, 0);
|
||||
redraw_timeouts (view);
|
||||
grub_video_swap_buffers ();
|
||||
if (view->double_repaint)
|
||||
redraw_timeouts (view);
|
||||
}
|
||||
|
||||
void
|
||||
grub_gfxmenu_clear_timeout (void *data)
|
||||
{
|
||||
struct grub_gfxmenu_view *view = data;
|
||||
|
||||
update_timeouts (0, 1, 0, 0);
|
||||
redraw_timeouts (view);
|
||||
grub_video_swap_buffers ();
|
||||
if (view->double_repaint)
|
||||
redraw_timeouts (view);
|
||||
}
|
||||
|
||||
static void
|
||||
update_menu_visit (grub_gui_component_t component,
|
||||
void *userdata)
|
||||
{
|
||||
grub_gfxmenu_view_t view;
|
||||
view = userdata;
|
||||
if (component->ops->is_instance (component, "list"))
|
||||
{
|
||||
grub_gui_list_t list = (grub_gui_list_t) component;
|
||||
list->ops->set_view_info (list, view);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update any boot menu components with the current menu model and
|
||||
theme path. */
|
||||
static void
|
||||
update_menu_components (grub_gfxmenu_view_t view)
|
||||
{
|
||||
grub_gui_iterate_recursively ((grub_gui_component_t) view->canvas,
|
||||
update_menu_visit, view);
|
||||
}
|
||||
|
||||
static void
|
||||
refresh_menu_visit (grub_gui_component_t component,
|
||||
void *userdata)
|
||||
{
|
||||
grub_gfxmenu_view_t view;
|
||||
view = userdata;
|
||||
if (component->ops->is_instance (component, "list"))
|
||||
{
|
||||
grub_gui_list_t list = (grub_gui_list_t) component;
|
||||
list->ops->refresh_list (list, view);
|
||||
}
|
||||
}
|
||||
|
||||
/* Refresh list information (useful for submenus) */
|
||||
static void
|
||||
refresh_menu_components (grub_gfxmenu_view_t view)
|
||||
{
|
||||
grub_gui_iterate_recursively ((grub_gui_component_t) view->canvas,
|
||||
refresh_menu_visit, view);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_message (grub_gfxmenu_view_t view)
|
||||
{
|
||||
char *text = view->progress_message_text;
|
||||
grub_video_rect_t f = view->progress_message_frame;
|
||||
if (! text)
|
||||
return;
|
||||
|
||||
grub_font_t font = view->message_font;
|
||||
grub_video_color_t color = grub_video_map_rgba_color (view->message_color);
|
||||
|
||||
/* Border. */
|
||||
grub_video_fill_rect (color,
|
||||
f.x-1, f.y-1, f.width+2, f.height+2);
|
||||
/* Fill. */
|
||||
grub_video_fill_rect (grub_video_map_rgba_color (view->message_bg_color),
|
||||
f.x, f.y, f.width, f.height);
|
||||
|
||||
/* Center the text. */
|
||||
int text_width = grub_font_get_string_width (font, text);
|
||||
int x = f.x + (f.width - text_width) / 2;
|
||||
int y = (f.y + (f.height - grub_font_get_descent (font)) / 2
|
||||
+ grub_font_get_ascent (font) / 2);
|
||||
grub_font_draw_string (text, font, color, x, y);
|
||||
}
|
||||
|
||||
void
|
||||
grub_gfxmenu_view_redraw (grub_gfxmenu_view_t view,
|
||||
const grub_video_rect_t *region)
|
||||
{
|
||||
if (grub_video_have_common_points (&view->terminal_rect, region))
|
||||
grub_gfxterm_schedule_repaint ();
|
||||
|
||||
grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
|
||||
grub_video_area_status_t area_status;
|
||||
grub_video_get_area_status (&area_status);
|
||||
if (area_status == GRUB_VIDEO_AREA_ENABLED)
|
||||
grub_video_set_region (region->x, region->y,
|
||||
region->width, region->height);
|
||||
|
||||
redraw_background (view, region);
|
||||
if (view->canvas)
|
||||
view->canvas->component.ops->paint (view->canvas, region);
|
||||
draw_title (view);
|
||||
if (grub_video_have_common_points (&view->progress_message_frame, region))
|
||||
draw_message (view);
|
||||
|
||||
if (area_status == GRUB_VIDEO_AREA_ENABLED)
|
||||
grub_video_set_area_status (GRUB_VIDEO_AREA_ENABLED);
|
||||
}
|
||||
|
||||
void
|
||||
grub_gfxmenu_view_draw (grub_gfxmenu_view_t view)
|
||||
{
|
||||
init_terminal (view);
|
||||
|
||||
init_background (view);
|
||||
|
||||
/* Clear the screen; there may be garbage left over in video memory. */
|
||||
grub_video_fill_rect (grub_video_map_rgb (0, 0, 0),
|
||||
view->screen.x, view->screen.y,
|
||||
view->screen.width, view->screen.height);
|
||||
grub_video_swap_buffers ();
|
||||
if (view->double_repaint)
|
||||
grub_video_fill_rect (grub_video_map_rgb (0, 0, 0),
|
||||
view->screen.x, view->screen.y,
|
||||
view->screen.width, view->screen.height);
|
||||
|
||||
refresh_menu_components (view);
|
||||
update_menu_components (view);
|
||||
|
||||
grub_video_set_area_status (GRUB_VIDEO_AREA_DISABLED);
|
||||
grub_gfxmenu_view_redraw (view, &view->screen);
|
||||
grub_video_swap_buffers ();
|
||||
if (view->double_repaint)
|
||||
{
|
||||
grub_video_set_area_status (GRUB_VIDEO_AREA_DISABLED);
|
||||
grub_gfxmenu_view_redraw (view, &view->screen);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
redraw_menu_visit (grub_gui_component_t component,
|
||||
void *userdata)
|
||||
{
|
||||
grub_gfxmenu_view_t view;
|
||||
view = userdata;
|
||||
if (component->ops->is_instance (component, "list"))
|
||||
{
|
||||
grub_video_rect_t bounds;
|
||||
|
||||
component->ops->get_bounds (component, &bounds);
|
||||
grub_video_set_area_status (GRUB_VIDEO_AREA_ENABLED);
|
||||
grub_gfxmenu_view_redraw (view, &bounds);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
grub_gfxmenu_redraw_menu (grub_gfxmenu_view_t view)
|
||||
{
|
||||
update_menu_components (view);
|
||||
|
||||
grub_gui_iterate_recursively ((grub_gui_component_t) view->canvas,
|
||||
redraw_menu_visit, view);
|
||||
grub_video_swap_buffers ();
|
||||
if (view->double_repaint)
|
||||
{
|
||||
grub_gui_iterate_recursively ((grub_gui_component_t) view->canvas,
|
||||
redraw_menu_visit, view);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
grub_gfxmenu_set_chosen_entry (int entry, void *data)
|
||||
{
|
||||
grub_gfxmenu_view_t view = data;
|
||||
|
||||
view->selected = entry;
|
||||
grub_gfxmenu_redraw_menu (view);
|
||||
}
|
||||
|
||||
static void
|
||||
grub_gfxmenu_draw_terminal_box (void)
|
||||
{
|
||||
grub_gfxmenu_box_t term_box;
|
||||
|
||||
term_box = term_view->terminal_box;
|
||||
if (!term_box)
|
||||
return;
|
||||
|
||||
grub_video_set_area_status (GRUB_VIDEO_AREA_DISABLED);
|
||||
|
||||
term_box->set_content_size (term_box, term_view->terminal_rect.width,
|
||||
term_view->terminal_rect.height);
|
||||
|
||||
term_box->draw (term_box,
|
||||
term_view->terminal_rect.x - term_box->get_left_pad (term_box),
|
||||
term_view->terminal_rect.y - term_box->get_top_pad (term_box));
|
||||
}
|
||||
|
||||
static void
|
||||
get_min_terminal (grub_font_t terminal_font,
|
||||
unsigned int border_width,
|
||||
unsigned int *min_terminal_width,
|
||||
unsigned int *min_terminal_height)
|
||||
{
|
||||
struct grub_font_glyph *glyph;
|
||||
glyph = grub_font_get_glyph (terminal_font, 'M');
|
||||
*min_terminal_width = (glyph? glyph->device_width : 8) * 80
|
||||
+ 2 * border_width;
|
||||
*min_terminal_height = grub_font_get_max_char_height (terminal_font) * 24
|
||||
+ 2 * border_width;
|
||||
}
|
||||
|
||||
static void
|
||||
terminal_sanity_check (grub_gfxmenu_view_t view)
|
||||
{
|
||||
if (!view->need_to_check_sanity)
|
||||
return;
|
||||
|
||||
/* terminal_font was checked before in the init_terminal function. */
|
||||
grub_font_t terminal_font = grub_font_get (view->terminal_font_name);
|
||||
|
||||
/* Non-negative numbers below. */
|
||||
int scr_x = view->screen.x;
|
||||
int scr_y = view->screen.y;
|
||||
int scr_width = view->screen.width;
|
||||
int scr_height = view->screen.height;
|
||||
int term_x = view->terminal_rect.x;
|
||||
int term_y = view->terminal_rect.y;
|
||||
int term_width = view->terminal_rect.width;
|
||||
int term_height = view->terminal_rect.height;
|
||||
|
||||
/* Check that border_width isn't too big. */
|
||||
unsigned int border_width = view->terminal_border;
|
||||
unsigned int min_terminal_width;
|
||||
unsigned int min_terminal_height;
|
||||
get_min_terminal (terminal_font, border_width,
|
||||
&min_terminal_width, &min_terminal_height);
|
||||
if (border_width > 3 && ((int) min_terminal_width >= scr_width
|
||||
|| (int) min_terminal_height >= scr_height))
|
||||
{
|
||||
border_width = 3;
|
||||
get_min_terminal (terminal_font, border_width,
|
||||
&min_terminal_width, &min_terminal_height);
|
||||
}
|
||||
|
||||
/* Sanity checks. */
|
||||
if (term_width > scr_width)
|
||||
term_width = scr_width;
|
||||
if (term_height > scr_height)
|
||||
term_height = scr_height;
|
||||
|
||||
if (scr_width <= (int) min_terminal_width
|
||||
|| scr_height <= (int) min_terminal_height)
|
||||
{
|
||||
/* The screen resulution is too low. Use all space, except a small border
|
||||
to show the user, that it is a window. Then center the window. */
|
||||
term_width = scr_width - 6 * border_width;
|
||||
term_height = scr_height - 6 * border_width;
|
||||
term_x = scr_x + (scr_width - term_width) / 2;
|
||||
term_y = scr_y + (scr_height - term_height) / 2;
|
||||
}
|
||||
else if (term_width < (int) min_terminal_width
|
||||
|| term_height < (int) min_terminal_height)
|
||||
{
|
||||
/* The screen resolution is big enough. Make sure, that terminal screen
|
||||
dimensions aren't less than minimal values. Then center the window. */
|
||||
term_width = (int) min_terminal_width;
|
||||
term_height = (int) min_terminal_height;
|
||||
term_x = scr_x + (scr_width - term_width) / 2;
|
||||
term_y = scr_y + (scr_height - term_height) / 2;
|
||||
}
|
||||
|
||||
/* At this point w and h are satisfying. */
|
||||
if (term_x + term_width > scr_width)
|
||||
term_x = scr_width - term_width;
|
||||
if (term_y + term_height > scr_height)
|
||||
term_y = scr_height - term_height;
|
||||
|
||||
/* Write down corrected data. */
|
||||
view->terminal_rect.x = (unsigned int) term_x;
|
||||
view->terminal_rect.y = (unsigned int) term_y;
|
||||
view->terminal_rect.width = (unsigned int) term_width;
|
||||
view->terminal_rect.height = (unsigned int) term_height;
|
||||
view->terminal_border = border_width;
|
||||
|
||||
view->need_to_check_sanity = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
init_terminal (grub_gfxmenu_view_t view)
|
||||
{
|
||||
grub_font_t terminal_font;
|
||||
|
||||
terminal_font = grub_font_get (view->terminal_font_name);
|
||||
if (!terminal_font)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_FONT, "no font loaded");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check that terminal window size and position are sane. */
|
||||
terminal_sanity_check (view);
|
||||
|
||||
term_view = view;
|
||||
|
||||
/* Note: currently there is no API for changing the gfxterm font
|
||||
on the fly, so whatever font the initially loaded theme specifies
|
||||
will be permanent. */
|
||||
grub_gfxterm_set_window (GRUB_VIDEO_RENDER_TARGET_DISPLAY,
|
||||
view->terminal_rect.x,
|
||||
view->terminal_rect.y,
|
||||
view->terminal_rect.width,
|
||||
view->terminal_rect.height,
|
||||
view->double_repaint,
|
||||
terminal_font,
|
||||
view->terminal_border);
|
||||
grub_gfxterm_decorator_hook = grub_gfxmenu_draw_terminal_box;
|
||||
}
|
||||
|
||||
static void
|
||||
init_background (grub_gfxmenu_view_t view)
|
||||
{
|
||||
if (view->scaled_desktop_image || (!view->raw_desktop_image))
|
||||
return;
|
||||
|
||||
struct grub_video_bitmap *scaled_bitmap;
|
||||
if (view->desktop_image_scale_method ==
|
||||
GRUB_VIDEO_BITMAP_SELECTION_METHOD_STRETCH)
|
||||
grub_video_bitmap_create_scaled (&scaled_bitmap,
|
||||
view->screen.width,
|
||||
view->screen.height,
|
||||
view->raw_desktop_image,
|
||||
GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST);
|
||||
else
|
||||
grub_video_bitmap_scale_proportional (&scaled_bitmap,
|
||||
view->screen.width,
|
||||
view->screen.height,
|
||||
view->raw_desktop_image,
|
||||
GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST,
|
||||
view->desktop_image_scale_method,
|
||||
view->desktop_image_v_align,
|
||||
view->desktop_image_h_align);
|
||||
if (! scaled_bitmap)
|
||||
return;
|
||||
view->scaled_desktop_image = scaled_bitmap;
|
||||
|
||||
}
|
||||
|
||||
/* FIXME: previously notifications were displayed in special case.
|
||||
Is it necessary?
|
||||
*/
|
||||
#if 0
|
||||
/* Sets MESSAGE as the progress message for the view.
|
||||
MESSAGE can be 0, in which case no message is displayed. */
|
||||
static void
|
||||
set_progress_message (grub_gfxmenu_view_t view, const char *message)
|
||||
{
|
||||
grub_free (view->progress_message_text);
|
||||
if (message)
|
||||
view->progress_message_text = grub_strdup (message);
|
||||
else
|
||||
view->progress_message_text = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
notify_booting (grub_menu_entry_t entry, void *userdata)
|
||||
{
|
||||
grub_gfxmenu_view_t view = (grub_gfxmenu_view_t) userdata;
|
||||
|
||||
char *s = grub_malloc (100 + grub_strlen (entry->title));
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
grub_sprintf (s, "Booting '%s'", entry->title);
|
||||
set_progress_message (view, s);
|
||||
grub_free (s);
|
||||
grub_gfxmenu_view_redraw (view, &view->progress_message_frame);
|
||||
grub_video_swap_buffers ();
|
||||
if (view->double_repaint)
|
||||
grub_gfxmenu_view_redraw (view, &view->progress_message_frame);
|
||||
}
|
||||
|
||||
static void
|
||||
notify_fallback (grub_menu_entry_t entry, void *userdata)
|
||||
{
|
||||
grub_gfxmenu_view_t view = (grub_gfxmenu_view_t) userdata;
|
||||
|
||||
char *s = grub_malloc (100 + grub_strlen (entry->title));
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
grub_sprintf (s, "Falling back to '%s'", entry->title);
|
||||
set_progress_message (view, s);
|
||||
grub_free (s);
|
||||
grub_gfxmenu_view_redraw (view, &view->progress_message_frame);
|
||||
grub_video_swap_buffers ();
|
||||
if (view->double_repaint)
|
||||
grub_gfxmenu_view_redraw (view, &view->progress_message_frame);
|
||||
}
|
||||
|
||||
static void
|
||||
notify_execution_failure (void *userdata __attribute__ ((unused)))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static struct grub_menu_execute_callback execute_callback =
|
||||
{
|
||||
.notify_booting = notify_booting,
|
||||
.notify_fallback = notify_fallback,
|
||||
.notify_failure = notify_execution_failure
|
||||
};
|
||||
|
||||
#endif
|
@@ -27,7 +27,7 @@
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/ventoy.h>
|
||||
|
||||
#define GRUB_CACHE_TIMEOUT 2
|
||||
#define GRUB_CACHE_TIMEOUT 10
|
||||
|
||||
/* The last time the disk was used. */
|
||||
static grub_uint64_t grub_last_time = 0;
|
||||
|
@@ -83,6 +83,29 @@ grub_file_t grub_memfile_open(const char *name)
|
||||
return file;
|
||||
}
|
||||
|
||||
int ventoy_check_file_exist(const char * fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
grub_file_t file;
|
||||
char fullpath[256] = {0};
|
||||
|
||||
va_start (ap, fmt);
|
||||
grub_vsnprintf(fullpath, 255, fmt, ap);
|
||||
va_end (ap);
|
||||
|
||||
file = grub_file_open(fullpath, GRUB_FILE_TYPE_NONE);
|
||||
if (!file)
|
||||
{
|
||||
grub_errno = 0;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_file_close(file);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
grub_file_t
|
||||
grub_file_open (const char *name, enum grub_file_type type)
|
||||
{
|
||||
|
@@ -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);
|
||||
|
||||
@@ -260,6 +306,45 @@ reclaim_module_space (void)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef GRUB_MACHINE_EFI
|
||||
static int ventoy_legacy_limit_workaround(void)
|
||||
{
|
||||
grub_file_t file;
|
||||
char *pos, *root;
|
||||
char buf[128];
|
||||
|
||||
root = grub_strdup(grub_env_get("root"));
|
||||
if (!root)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
pos = grub_strchr(root, ',');
|
||||
if (pos) *pos = 0;
|
||||
|
||||
grub_snprintf(buf, sizeof(buf), "(%s,1)/ventoy/ventoy.disk.img.xz", root);
|
||||
file = grub_file_open(buf, GRUB_FILE_TYPE_NONE);
|
||||
if (file)
|
||||
{
|
||||
pos = grub_malloc(file->size);
|
||||
if (pos)
|
||||
{
|
||||
grub_file_read(file, pos, file->size);
|
||||
grub_snprintf(buf, sizeof(buf), "loopback ventoydisk mem:0x%lx:size:%lu",
|
||||
(unsigned long)pos, (unsigned long)file->size);
|
||||
|
||||
grub_parser_execute(buf);
|
||||
grub_env_set("prefix", "(ventoydisk)/grub");
|
||||
}
|
||||
|
||||
grub_file_close(file);
|
||||
}
|
||||
|
||||
grub_free(root);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* The main routine. */
|
||||
void __attribute__ ((noreturn))
|
||||
grub_main (void)
|
||||
@@ -293,6 +378,12 @@ grub_main (void)
|
||||
grub_env_export ("root");
|
||||
grub_env_export ("prefix");
|
||||
|
||||
#ifndef GRUB_MACHINE_EFI
|
||||
if (0 == ventoy_check_file_exist("%s/grub.cfg", grub_env_get("prefix"))) {
|
||||
ventoy_legacy_limit_workaround();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Reclaim space used for modules. */
|
||||
reclaim_module_space ();
|
||||
|
||||
|
1559
GRUB2/MOD_SRC/grub-2.04/grub-core/lib/syslinux_parse.c
Normal file
1585
GRUB2/MOD_SRC/grub-2.04/grub-core/loader/i386/linux.c
Normal file
@@ -99,7 +99,7 @@ grub_env_new_context (int export_all)
|
||||
grub_err_t
|
||||
grub_env_context_open (void)
|
||||
{
|
||||
return grub_env_new_context (1);
|
||||
return grub_env_new_context (grub_env_get("ventoy_new_context") ? 0 : 1);
|
||||
}
|
||||
|
||||
int grub_extractor_level = 0;
|
||||
|
575
GRUB2/MOD_SRC/grub-2.04/grub-core/normal/main.c
Normal file
@@ -0,0 +1,575 @@
|
||||
/* main.c - the normal mode main routine */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2000,2001,2002,2003,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/kernel.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/menu.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/parser.h>
|
||||
#include <grub/reader.h>
|
||||
#include <grub/menu_viewer.h>
|
||||
#include <grub/auth.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/charset.h>
|
||||
#include <grub/script_sh.h>
|
||||
#include <grub/bufio.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
#define GRUB_DEFAULT_HISTORY_SIZE 50
|
||||
|
||||
static int nested_level = 0;
|
||||
int grub_normal_exit_level = 0;
|
||||
|
||||
void
|
||||
grub_normal_free_menu (grub_menu_t menu)
|
||||
{
|
||||
grub_menu_entry_t entry = menu->entry_list;
|
||||
|
||||
while (entry)
|
||||
{
|
||||
grub_menu_entry_t next_entry = entry->next;
|
||||
grub_size_t i;
|
||||
|
||||
if (entry->classes)
|
||||
{
|
||||
struct grub_menu_entry_class *class;
|
||||
for (class = entry->classes; class; class = class->next)
|
||||
grub_free (class->name);
|
||||
grub_free (entry->classes);
|
||||
}
|
||||
|
||||
if (entry->args)
|
||||
{
|
||||
for (i = 0; entry->args[i]; i++)
|
||||
grub_free (entry->args[i]);
|
||||
grub_free (entry->args);
|
||||
}
|
||||
|
||||
if (entry->bls)
|
||||
{
|
||||
entry->bls->visible = 0;
|
||||
}
|
||||
|
||||
grub_free ((void *) entry->id);
|
||||
grub_free ((void *) entry->users);
|
||||
grub_free ((void *) entry->title);
|
||||
grub_free ((void *) entry->sourcecode);
|
||||
grub_free (entry);
|
||||
entry = next_entry;
|
||||
}
|
||||
|
||||
grub_free (menu);
|
||||
grub_env_unset_menu ();
|
||||
}
|
||||
|
||||
/* Helper for read_config_file. */
|
||||
static grub_err_t
|
||||
read_config_file_getline (char **line, int cont __attribute__ ((unused)),
|
||||
void *data)
|
||||
{
|
||||
grub_file_t file = data;
|
||||
|
||||
while (1)
|
||||
{
|
||||
char *buf;
|
||||
|
||||
*line = buf = grub_file_getline (file);
|
||||
if (! buf)
|
||||
return grub_errno;
|
||||
|
||||
if (buf[0] == '#')
|
||||
grub_free (*line);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_menu_t
|
||||
read_config_file (const char *config)
|
||||
{
|
||||
grub_file_t rawfile, file;
|
||||
char *old_file = 0, *old_dir = 0;
|
||||
char *config_dir, *ptr = 0;
|
||||
const char *ctmp;
|
||||
|
||||
grub_menu_t newmenu;
|
||||
|
||||
newmenu = grub_env_get_menu ();
|
||||
if (! newmenu)
|
||||
{
|
||||
newmenu = grub_zalloc (sizeof (*newmenu));
|
||||
if (! newmenu)
|
||||
return 0;
|
||||
|
||||
grub_env_set_menu (newmenu);
|
||||
}
|
||||
|
||||
/* Try to open the config file. */
|
||||
rawfile = grub_file_open (config, GRUB_FILE_TYPE_CONFIG);
|
||||
if (! rawfile)
|
||||
return 0;
|
||||
|
||||
file = grub_bufio_open (rawfile, 0);
|
||||
if (! file)
|
||||
{
|
||||
grub_file_close (rawfile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctmp = grub_env_get ("config_file");
|
||||
if (ctmp)
|
||||
old_file = grub_strdup (ctmp);
|
||||
ctmp = grub_env_get ("config_directory");
|
||||
if (ctmp)
|
||||
old_dir = grub_strdup (ctmp);
|
||||
if (*config == '(')
|
||||
{
|
||||
grub_env_set ("config_file", config);
|
||||
config_dir = grub_strdup (config);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* $root is guranteed to be defined, otherwise open above would fail */
|
||||
config_dir = grub_xasprintf ("(%s)%s", grub_env_get ("root"), config);
|
||||
if (config_dir)
|
||||
grub_env_set ("config_file", config_dir);
|
||||
}
|
||||
if (config_dir)
|
||||
{
|
||||
ptr = grub_strrchr (config_dir, '/');
|
||||
if (ptr)
|
||||
*ptr = 0;
|
||||
grub_env_set ("config_directory", config_dir);
|
||||
grub_free (config_dir);
|
||||
}
|
||||
|
||||
grub_env_export ("config_file");
|
||||
grub_env_export ("config_directory");
|
||||
|
||||
while (1)
|
||||
{
|
||||
char *line;
|
||||
|
||||
/* Print an error, if any. */
|
||||
grub_print_error ();
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
|
||||
if ((read_config_file_getline (&line, 0, file)) || (! line))
|
||||
break;
|
||||
|
||||
grub_normal_parse_line (line, read_config_file_getline, file);
|
||||
grub_free (line);
|
||||
}
|
||||
|
||||
if (old_file)
|
||||
grub_env_set ("config_file", old_file);
|
||||
else
|
||||
grub_env_unset ("config_file");
|
||||
if (old_dir)
|
||||
grub_env_set ("config_directory", old_dir);
|
||||
else
|
||||
grub_env_unset ("config_directory");
|
||||
grub_free (old_file);
|
||||
grub_free (old_dir);
|
||||
|
||||
grub_file_close (file);
|
||||
|
||||
return newmenu;
|
||||
}
|
||||
|
||||
/* Initialize the screen. */
|
||||
void
|
||||
grub_normal_init_page (struct grub_term_output *term,
|
||||
int y)
|
||||
{
|
||||
grub_ssize_t msg_len;
|
||||
int posx;
|
||||
char *msg_formatted;
|
||||
grub_uint32_t *unicode_msg;
|
||||
grub_uint32_t *last_position;
|
||||
|
||||
grub_term_cls (term);
|
||||
|
||||
msg_formatted = grub_xasprintf (_("GNU GRUB version %s"), PACKAGE_VERSION);
|
||||
if (!msg_formatted)
|
||||
return;
|
||||
|
||||
msg_len = grub_utf8_to_ucs4_alloc (msg_formatted,
|
||||
&unicode_msg, &last_position);
|
||||
grub_free (msg_formatted);
|
||||
|
||||
if (msg_len < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
posx = grub_getstringwidth (unicode_msg, last_position, term);
|
||||
posx = ((int) grub_term_width (term) - posx) / 2;
|
||||
if (posx < 0)
|
||||
posx = 0;
|
||||
grub_term_gotoxy (term, (struct grub_term_coordinate) { posx, y });
|
||||
|
||||
grub_print_ucs4 (unicode_msg, last_position, 0, 0, term);
|
||||
grub_putcode ('\n', term);
|
||||
grub_putcode ('\n', term);
|
||||
grub_free (unicode_msg);
|
||||
}
|
||||
|
||||
static void
|
||||
read_lists (const char *val)
|
||||
{
|
||||
if (! grub_no_modules)
|
||||
{
|
||||
read_command_list (val);
|
||||
read_fs_list (val);
|
||||
read_crypto_list (val);
|
||||
read_terminal_list (val);
|
||||
}
|
||||
grub_gettext_reread_prefix (val);
|
||||
}
|
||||
|
||||
static char *
|
||||
read_lists_hook (struct grub_env_var *var __attribute__ ((unused)),
|
||||
const char *val)
|
||||
{
|
||||
read_lists (val);
|
||||
return val ? grub_strdup (val) : NULL;
|
||||
}
|
||||
|
||||
/* Read the config file CONFIG and execute the menu interface or
|
||||
the command line interface if BATCH is false. */
|
||||
void
|
||||
grub_normal_execute (const char *config, int nested, int batch)
|
||||
{
|
||||
grub_menu_t menu = 0;
|
||||
const char *prefix;
|
||||
|
||||
if (! nested)
|
||||
{
|
||||
prefix = grub_env_get ("prefix");
|
||||
read_lists (prefix);
|
||||
grub_register_variable_hook ("prefix", NULL, read_lists_hook);
|
||||
}
|
||||
|
||||
grub_boot_time ("Executing config file");
|
||||
|
||||
if (config)
|
||||
{
|
||||
menu = read_config_file (config);
|
||||
|
||||
/* Ignore any error. */
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
grub_boot_time ("Executed config file");
|
||||
|
||||
if (! batch)
|
||||
{
|
||||
if (menu && menu->size)
|
||||
{
|
||||
|
||||
grub_boot_time ("Entering menu");
|
||||
grub_show_menu (menu, nested, 0);
|
||||
if (nested)
|
||||
grub_normal_free_menu (menu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This starts the normal mode. */
|
||||
void
|
||||
grub_enter_normal_mode (const char *config)
|
||||
{
|
||||
grub_boot_time ("Entering normal mode");
|
||||
nested_level++;
|
||||
grub_normal_execute (config, 0, 0);
|
||||
grub_boot_time ("Entering shell");
|
||||
grub_cmdline_run (0, 1);
|
||||
nested_level--;
|
||||
if (grub_normal_exit_level)
|
||||
grub_normal_exit_level--;
|
||||
grub_boot_time ("Exiting normal mode");
|
||||
}
|
||||
|
||||
/* Enter normal mode from rescue mode. */
|
||||
static grub_err_t
|
||||
grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
if (argc == 0)
|
||||
{
|
||||
/* Guess the config filename. It is necessary to make CONFIG static,
|
||||
so that it won't get broken by longjmp. */
|
||||
char *config;
|
||||
const char *prefix;
|
||||
|
||||
prefix = grub_env_get ("prefix");
|
||||
if (prefix)
|
||||
{
|
||||
config = grub_xasprintf ("%s/grub.cfg", prefix);
|
||||
if (! config)
|
||||
goto quit;
|
||||
|
||||
grub_enter_normal_mode (config);
|
||||
grub_free (config);
|
||||
}
|
||||
else
|
||||
grub_enter_normal_mode (0);
|
||||
}
|
||||
else
|
||||
grub_enter_normal_mode (argv[0]);
|
||||
|
||||
quit:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Exit from normal mode to rescue mode. */
|
||||
static grub_err_t
|
||||
grub_cmd_normal_exit (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char *argv[] __attribute__ ((unused)))
|
||||
{
|
||||
if (nested_level <= grub_normal_exit_level)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "not in normal environment");
|
||||
grub_normal_exit_level++;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_normal_reader_init (int nested)
|
||||
{
|
||||
struct grub_term_output *term;
|
||||
const char *msg_esc = _("ESC at any time exits.");
|
||||
char *msg_formatted;
|
||||
|
||||
msg_formatted = grub_xasprintf (_("Minimal BASH-like line editing is supported. For "
|
||||
"the first word, TAB lists possible command completions. Anywhere "
|
||||
"else TAB lists possible device or file completions. %s"),
|
||||
nested ? msg_esc : "");
|
||||
if (!msg_formatted)
|
||||
return grub_errno;
|
||||
|
||||
FOR_ACTIVE_TERM_OUTPUTS(term)
|
||||
{
|
||||
grub_normal_init_page (term, 1);
|
||||
grub_term_setcursor (term, 1);
|
||||
|
||||
if (grub_term_width (term) > 3 + STANDARD_MARGIN + 20)
|
||||
grub_print_message_indented (msg_formatted, 3, STANDARD_MARGIN, term);
|
||||
else
|
||||
grub_print_message_indented (msg_formatted, 0, 0, term);
|
||||
grub_putcode ('\n', term);
|
||||
grub_putcode ('\n', term);
|
||||
grub_putcode ('\n', term);
|
||||
}
|
||||
grub_free (msg_formatted);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_normal_read_line_real (char **line, int cont, int nested)
|
||||
{
|
||||
const char *prompt;
|
||||
|
||||
if (cont)
|
||||
/* TRANSLATORS: it's command line prompt. */
|
||||
prompt = _(">");
|
||||
else
|
||||
/* TRANSLATORS: it's command line prompt. */
|
||||
prompt = _("grub>");
|
||||
|
||||
if (!prompt)
|
||||
return grub_errno;
|
||||
|
||||
while (1)
|
||||
{
|
||||
*line = grub_cmdline_get (prompt);
|
||||
if (*line)
|
||||
return 0;
|
||||
|
||||
if (cont || nested)
|
||||
{
|
||||
grub_free (*line);
|
||||
*line = 0;
|
||||
return grub_errno;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_normal_read_line (char **line, int cont,
|
||||
void *data __attribute__ ((unused)))
|
||||
{
|
||||
return grub_normal_read_line_real (line, cont, 0);
|
||||
}
|
||||
|
||||
void
|
||||
grub_cmdline_run (int nested, int force_auth)
|
||||
{
|
||||
grub_err_t err = GRUB_ERR_NONE;
|
||||
|
||||
do
|
||||
{
|
||||
err = grub_auth_check_authentication (NULL);
|
||||
}
|
||||
while (err && force_auth);
|
||||
|
||||
if (err)
|
||||
{
|
||||
grub_print_error ();
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
grub_normal_reader_init (nested);
|
||||
|
||||
while (1)
|
||||
{
|
||||
char *line = NULL;
|
||||
|
||||
if (grub_normal_exit_level)
|
||||
break;
|
||||
|
||||
/* Print an error, if any. */
|
||||
grub_print_error ();
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
|
||||
grub_normal_read_line_real (&line, 0, nested);
|
||||
if (! line)
|
||||
break;
|
||||
|
||||
grub_normal_parse_line (line, grub_normal_read_line, NULL);
|
||||
grub_free (line);
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
grub_env_write_pager (struct grub_env_var *var __attribute__ ((unused)),
|
||||
const char *val)
|
||||
{
|
||||
grub_set_more ((*val == '1'));
|
||||
return grub_strdup (val);
|
||||
}
|
||||
|
||||
/* clear */
|
||||
static grub_err_t
|
||||
grub_mini_cmd_clear (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char *argv[] __attribute__ ((unused)))
|
||||
{
|
||||
grub_cls ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_command_t cmd_clear;
|
||||
|
||||
static void (*grub_xputs_saved) (const char *str);
|
||||
static const char *features[] = {
|
||||
"feature_chainloader_bpb", "feature_ntldr", "feature_platform_search_hint",
|
||||
"feature_default_font_path", "feature_all_video_module",
|
||||
"feature_menuentry_id", "feature_menuentry_options", "feature_200_final",
|
||||
"feature_nativedisk_cmd", "feature_timeout_style"
|
||||
};
|
||||
|
||||
GRUB_MOD_INIT(normal)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
grub_boot_time ("Preparing normal module");
|
||||
|
||||
/* Previously many modules depended on gzio. Be nice to user and load it. */
|
||||
grub_dl_load ("gzio");
|
||||
grub_errno = 0;
|
||||
|
||||
grub_normal_auth_init ();
|
||||
grub_context_init ();
|
||||
grub_script_init ();
|
||||
grub_menu_init ();
|
||||
|
||||
grub_xputs_saved = grub_xputs;
|
||||
grub_xputs = grub_xputs_normal;
|
||||
|
||||
/* Normal mode shouldn't be unloaded. */
|
||||
if (mod)
|
||||
grub_dl_ref (mod);
|
||||
|
||||
cmd_clear =
|
||||
grub_register_command ("clear", grub_mini_cmd_clear,
|
||||
0, N_("Clear the screen."));
|
||||
|
||||
grub_set_history (GRUB_DEFAULT_HISTORY_SIZE);
|
||||
|
||||
grub_register_variable_hook ("pager", 0, grub_env_write_pager);
|
||||
grub_env_export ("pager");
|
||||
|
||||
/* Register a command "normal" for the rescue mode. */
|
||||
grub_register_command ("normal", grub_cmd_normal,
|
||||
0, N_("Enter normal mode."));
|
||||
grub_register_command ("normal_exit", grub_cmd_normal_exit,
|
||||
0, N_("Exit from normal mode."));
|
||||
|
||||
/* Reload terminal colors when these variables are written to. */
|
||||
grub_register_variable_hook ("color_normal", NULL, grub_env_write_color_normal);
|
||||
grub_register_variable_hook ("color_highlight", NULL, grub_env_write_color_highlight);
|
||||
|
||||
/* Preserve hooks after context changes. */
|
||||
grub_env_export ("color_normal");
|
||||
grub_env_export ("color_highlight");
|
||||
|
||||
/* Set default color names. */
|
||||
grub_env_set ("color_normal", "light-gray/black");
|
||||
grub_env_set ("color_highlight", "black/light-gray");
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE (features); i++)
|
||||
{
|
||||
grub_env_set (features[i], "y");
|
||||
grub_env_export (features[i]);
|
||||
}
|
||||
grub_env_set ("grub_cpu", GRUB_TARGET_CPU);
|
||||
grub_env_export ("grub_cpu");
|
||||
grub_env_set ("grub_platform", GRUB_PLATFORM);
|
||||
grub_env_export ("grub_platform");
|
||||
|
||||
grub_boot_time ("Normal module prepared");
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(normal)
|
||||
{
|
||||
grub_context_fini ();
|
||||
grub_script_fini ();
|
||||
grub_menu_fini ();
|
||||
grub_normal_auth_fini ();
|
||||
|
||||
grub_xputs = grub_xputs_saved;
|
||||
|
||||
grub_set_history (0);
|
||||
grub_register_variable_hook ("pager", 0, 0);
|
||||
grub_fs_autoload_hook = 0;
|
||||
grub_unregister_command (cmd_clear);
|
||||
}
|
@@ -38,9 +38,10 @@ int g_ventoy_menu_refresh = 0;
|
||||
int g_ventoy_memdisk_mode = 0;
|
||||
int g_ventoy_iso_raw = 0;
|
||||
int g_ventoy_iso_uefi_drv = 0;
|
||||
int g_ventoy_last_entry = 0;
|
||||
int g_ventoy_last_entry = -1;
|
||||
int g_ventoy_suppress_esc = 0;
|
||||
int g_ventoy_menu_esc = 0;
|
||||
int g_ventoy_fn_mutex = 0;
|
||||
|
||||
/* Time to delay after displaying an error message about a default/fallback
|
||||
entry failing to boot. */
|
||||
@@ -802,51 +803,75 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
|
||||
goto refresh;
|
||||
|
||||
case GRUB_TERM_KEY_F2:
|
||||
cmdstr = grub_env_get("VTOY_F2_CMD");
|
||||
if (cmdstr)
|
||||
{
|
||||
menu_fini ();
|
||||
grub_script_execute_sourcecode(cmdstr);
|
||||
goto refresh;
|
||||
case '2':
|
||||
if (0 == g_ventoy_fn_mutex) {
|
||||
cmdstr = grub_env_get("VTOY_F2_CMD");
|
||||
if (cmdstr)
|
||||
{
|
||||
menu_fini ();
|
||||
g_ventoy_fn_mutex = 1;
|
||||
grub_script_execute_sourcecode(cmdstr);
|
||||
g_ventoy_fn_mutex = 0;
|
||||
goto refresh;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GRUB_TERM_KEY_F3:
|
||||
cmdstr = grub_env_get("VTOY_F3_CMD");
|
||||
if (cmdstr)
|
||||
{
|
||||
menu_fini ();
|
||||
grub_script_execute_sourcecode(cmdstr);
|
||||
goto refresh;
|
||||
case '3':
|
||||
if (0 == g_ventoy_fn_mutex) {
|
||||
cmdstr = grub_env_get("VTOY_F3_CMD");
|
||||
if (cmdstr)
|
||||
{
|
||||
menu_fini ();
|
||||
grub_script_execute_sourcecode(cmdstr);
|
||||
goto refresh;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GRUB_TERM_KEY_F4:
|
||||
cmdstr = grub_env_get("VTOY_F4_CMD");
|
||||
if (cmdstr)
|
||||
{
|
||||
menu_fini ();
|
||||
grub_script_execute_sourcecode(cmdstr);
|
||||
goto refresh;
|
||||
case '4':
|
||||
if (0 == g_ventoy_fn_mutex) {
|
||||
cmdstr = grub_env_get("VTOY_F4_CMD");
|
||||
if (cmdstr)
|
||||
{
|
||||
menu_fini ();
|
||||
g_ventoy_fn_mutex = 1;
|
||||
grub_script_execute_sourcecode(cmdstr);
|
||||
g_ventoy_fn_mutex = 0;
|
||||
goto refresh;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GRUB_TERM_KEY_F5:
|
||||
cmdstr = grub_env_get("VTOY_F5_CMD");
|
||||
if (cmdstr)
|
||||
{
|
||||
menu_fini ();
|
||||
grub_script_execute_sourcecode(cmdstr);
|
||||
goto refresh;
|
||||
case '5':
|
||||
if (0 == g_ventoy_fn_mutex) {
|
||||
cmdstr = grub_env_get("VTOY_F5_CMD");
|
||||
if (cmdstr)
|
||||
{
|
||||
menu_fini ();
|
||||
g_ventoy_fn_mutex = 1;
|
||||
grub_script_execute_sourcecode(cmdstr);
|
||||
g_ventoy_fn_mutex = 0;
|
||||
goto refresh;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GRUB_TERM_KEY_F6:
|
||||
cmdstr = grub_env_get("VTOY_F6_CMD");
|
||||
if (cmdstr)
|
||||
{
|
||||
menu_fini ();
|
||||
grub_script_execute_sourcecode(cmdstr);
|
||||
goto refresh;
|
||||
case '6':
|
||||
if (0 == g_ventoy_fn_mutex) {
|
||||
cmdstr = grub_env_get("VTOY_F6_CMD");
|
||||
if (cmdstr)
|
||||
{
|
||||
menu_fini ();
|
||||
g_ventoy_fn_mutex = 1;
|
||||
grub_script_execute_sourcecode(cmdstr);
|
||||
g_ventoy_fn_mutex = 0;
|
||||
goto refresh;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GRUB_TERM_KEY_F7:
|
||||
case '7':
|
||||
cmdstr = grub_env_get("VTOY_F7_CMD");
|
||||
if (cmdstr)
|
||||
{
|
||||
@@ -856,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;
|
||||
@@ -943,19 +969,28 @@ static struct grub_menu_execute_callback execution_callback =
|
||||
static grub_err_t
|
||||
show_menu (grub_menu_t menu, int nested, int autobooted)
|
||||
{
|
||||
const char *def;
|
||||
def = grub_env_get("VTOY_DEFAULT_IMAGE");
|
||||
|
||||
while (1)
|
||||
{
|
||||
int boot_entry;
|
||||
grub_menu_entry_t e;
|
||||
int auto_boot;
|
||||
|
||||
|
||||
boot_entry = run_menu (menu, nested, &auto_boot);
|
||||
if (boot_entry < 0)
|
||||
break;
|
||||
|
||||
g_ventoy_last_entry = boot_entry;
|
||||
if (g_ventoy_menu_esc)
|
||||
break;
|
||||
if (auto_boot && def && grub_strcmp(def, "VTOY_EXIT") == 0) {
|
||||
grub_exit();
|
||||
}
|
||||
|
||||
if (autobooted == 0 && auto_boot == 0) {
|
||||
g_ventoy_last_entry = boot_entry;
|
||||
if (g_ventoy_menu_esc)
|
||||
break;
|
||||
}
|
||||
|
||||
e = grub_menu_get_entry (menu, boot_entry);
|
||||
if (! e)
|
||||
@@ -973,6 +1008,9 @@ show_menu (grub_menu_t menu, int nested, int autobooted)
|
||||
grub_menu_execute_entry (e, 0);
|
||||
if (autobooted)
|
||||
break;
|
||||
|
||||
if (2 == e->argc && e->args && e->args[1] && grub_strncmp(e->args[1], "VTOY_RUN_RET", 12) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
|
@@ -180,22 +180,31 @@ 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
|
||||
{
|
||||
char szLine[128];
|
||||
const char *checkret = grub_env_get("VTOY_CHKDEV_RESULT_STRING");
|
||||
if (checkret == NULL || checkret[0] != '0') {
|
||||
grub_snprintf(szLine, sizeof(szLine), "%s [Unofficial Ventoy]", grub_env_get("VTOY_TEXT_MENU_VER"));
|
||||
} else {
|
||||
grub_snprintf(szLine, sizeof(szLine), "%s", grub_env_get("VTOY_TEXT_MENU_VER"));
|
||||
}
|
||||
|
||||
ret += grub_print_message_indented_real("\n", STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
|
||||
|
||||
ret += grub_print_message_indented_real(grub_env_get("VTOY_TEXT_MENU_VER"),
|
||||
STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
|
||||
ret += grub_print_message_indented_real(szLine, STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
|
||||
|
||||
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;
|
||||
|
@@ -23,10 +23,14 @@
|
||||
|
||||
#define VTOY_MAX_SCRIPT_BUF (4 * 1024 * 1024)
|
||||
|
||||
#define VTOY_PART_BUF_LEN (128 * 1024)
|
||||
|
||||
#define VTOY_FILT_MIN_FILE_SIZE 32768
|
||||
|
||||
#define VTOY_SIZE_1GB 1073741824
|
||||
#define VTOY_SIZE_512KB (512 * 1024)
|
||||
#define VTOY_SIZE_1MB (1024 * 1024)
|
||||
#define VTOY_SIZE_512KB (512 * 1024)
|
||||
#define VTOY_SIZE_1KB 1024
|
||||
|
||||
#define JSON_SUCCESS 0
|
||||
#define JSON_FAILED 1
|
||||
@@ -46,6 +50,14 @@
|
||||
#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 !!!!!!!!!!!!!"
|
||||
|
||||
#ifdef GRUB_MACHINE_EFI
|
||||
#define VTOY_DUAL_MODE_SUFFIX "uefi"
|
||||
#else
|
||||
#define VTOY_DUAL_MODE_SUFFIX "legacy"
|
||||
#endif
|
||||
|
||||
typedef struct ventoy_initrd_ctx
|
||||
{
|
||||
const char *path_prefix;
|
||||
@@ -97,6 +109,18 @@ typedef int (*grub_char_check_func)(int c);
|
||||
#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
|
||||
@@ -123,17 +147,38 @@ typedef struct ventoy_udf_override
|
||||
grub_uint32_t position;
|
||||
}ventoy_udf_override;
|
||||
|
||||
typedef struct ventoy_iso9660_vd
|
||||
{
|
||||
grub_uint8_t type;
|
||||
grub_uint8_t id[5];
|
||||
grub_uint8_t ver;
|
||||
grub_uint8_t res;
|
||||
char sys[32];
|
||||
char vol[32];
|
||||
}ventoy_iso9660_vd;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
#define img_type_iso 0
|
||||
#define img_type_wim 1
|
||||
#define img_type_iso 0
|
||||
#define img_type_wim 1
|
||||
#define img_type_efi 2
|
||||
#define img_type_img 3
|
||||
#define img_type_vhd 4
|
||||
#define img_type_vtoy 5
|
||||
|
||||
typedef struct img_info
|
||||
{
|
||||
int pathlen;
|
||||
char path[512];
|
||||
char name[256];
|
||||
|
||||
const char *alias;
|
||||
const char *class;
|
||||
const char *menu_prefix;
|
||||
|
||||
int id;
|
||||
int type;
|
||||
int plugin_list_index;
|
||||
grub_uint64_t size;
|
||||
int select;
|
||||
int unsupport;
|
||||
@@ -154,6 +199,8 @@ typedef struct img_iterator_node
|
||||
int done;
|
||||
int select;
|
||||
|
||||
int plugin_list_index;
|
||||
|
||||
struct img_iterator_node *parent;
|
||||
struct img_iterator_node *firstchild;
|
||||
|
||||
@@ -217,6 +264,7 @@ void ventoy_debug(const char *fmt, ...);
|
||||
#define FLAG_HEADER_COMPRESS_RESERVED 0x00010000
|
||||
#define FLAG_HEADER_COMPRESS_XPRESS 0x00020000
|
||||
#define FLAG_HEADER_COMPRESS_LZX 0x00040000
|
||||
#define FLAG_HEADER_COMPRESS_LZMS 0x00080000
|
||||
|
||||
#define RESHDR_FLAG_FREE 0x01
|
||||
#define RESHDR_FLAG_METADATA 0x02
|
||||
@@ -363,6 +411,19 @@ typedef struct wim_tail
|
||||
grub_uint32_t new_lookup_align_len;
|
||||
}wim_tail;
|
||||
|
||||
typedef struct wim_patch
|
||||
{
|
||||
int pathlen;
|
||||
char path[256];
|
||||
|
||||
wim_hash old_hash;
|
||||
wim_tail wim_data;
|
||||
wim_lookup_entry *replace_look;
|
||||
|
||||
int valid;
|
||||
|
||||
struct wim_patch *next;
|
||||
}wim_patch;
|
||||
|
||||
|
||||
typedef enum _JSON_TYPE
|
||||
@@ -412,11 +473,13 @@ typedef struct _JSON_PARSE
|
||||
}
|
||||
|
||||
typedef int (*ventoy_plugin_entry_pf)(VTOY_JSON *json, const char *isodisk);
|
||||
typedef int (*ventoy_plugin_check_pf)(VTOY_JSON *json, const char *isodisk);
|
||||
|
||||
typedef struct plugin_entry
|
||||
{
|
||||
const char *key;
|
||||
ventoy_plugin_entry_pf entryfunc;
|
||||
ventoy_plugin_check_pf checkfunc;
|
||||
}plugin_entry;
|
||||
|
||||
|
||||
@@ -433,16 +496,20 @@ 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_cpio_busybox_64(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, ...);
|
||||
int ventoy_is_file_exist(const char *fmt, ...);
|
||||
int ventoy_is_dir_exist(const char *fmt, ...);
|
||||
int ventoy_fill_data(grub_uint32_t buflen, char *buffer);
|
||||
grub_err_t ventoy_cmd_load_plugin(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_wimdows_reset(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_wimdows_locate_wim(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_windows_chain_data(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_wim_chain_data(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_wim_check_bootable(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_dump_wim_patch(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
|
||||
VTOY_JSON *vtoy_json_find_item
|
||||
(
|
||||
@@ -565,8 +632,88 @@ typedef struct ventoy_mbr_head
|
||||
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;
|
||||
|
||||
typedef struct vhd_footer_t
|
||||
{
|
||||
char cookie[8]; // Cookie
|
||||
grub_uint32_t features; // Features
|
||||
grub_uint32_t ffversion; // File format version
|
||||
grub_uint32_t dataoffset; // Data offset
|
||||
grub_uint32_t timestamp; // Timestamp
|
||||
grub_uint32_t creatorapp; // Creator application
|
||||
grub_uint32_t creatorver; // Creator version
|
||||
grub_uint32_t creatorhos; // Creator host OS
|
||||
grub_uint32_t origsize; // Original size
|
||||
grub_uint32_t currsize; // Current size
|
||||
grub_uint32_t diskgeom; // Disk geometry
|
||||
grub_uint32_t disktype; // Disk type
|
||||
grub_uint32_t checksum; // Checksum
|
||||
grub_uint8_t uniqueid[16]; // Unique ID
|
||||
grub_uint8_t savedst; // Saved state
|
||||
}vhd_footer_t;
|
||||
|
||||
#define VDI_IMAGE_FILE_INFO "<<< Oracle VM VirtualBox Disk Image >>>\n"
|
||||
|
||||
/** Image signature. */
|
||||
#define VDI_IMAGE_SIGNATURE (0xbeda107f)
|
||||
|
||||
typedef struct VDIPREHEADER
|
||||
{
|
||||
/** Just text info about image type, for eyes only. */
|
||||
char szFileInfo[64];
|
||||
/** The image signature (VDI_IMAGE_SIGNATURE). */
|
||||
grub_uint32_t u32Signature;
|
||||
/** The image version (VDI_IMAGE_VERSION). */
|
||||
grub_uint32_t u32Version;
|
||||
} VDIPREHEADER, *PVDIPREHEADER;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
typedef struct ventoy_video_mode
|
||||
{
|
||||
grub_uint32_t width;
|
||||
grub_uint32_t height;
|
||||
grub_uint32_t bpp;
|
||||
}ventoy_video_mode;
|
||||
|
||||
|
||||
|
||||
typedef struct file_fullpath
|
||||
{
|
||||
char path[256];
|
||||
@@ -577,6 +724,7 @@ typedef struct install_template
|
||||
int pathlen;
|
||||
char isopath[256];
|
||||
|
||||
int autosel;
|
||||
int cursel;
|
||||
int templatenum;
|
||||
file_fullpath *templatepath;
|
||||
@@ -584,11 +732,30 @@ typedef struct install_template
|
||||
struct install_template *next;
|
||||
}install_template;
|
||||
|
||||
typedef struct dudfile
|
||||
{
|
||||
int size;
|
||||
char *buf;
|
||||
}dudfile;
|
||||
|
||||
typedef struct dud
|
||||
{
|
||||
int pathlen;
|
||||
char isopath[256];
|
||||
|
||||
int dudnum;
|
||||
file_fullpath *dudpath;
|
||||
dudfile *files;
|
||||
|
||||
struct dud *next;
|
||||
}dud;
|
||||
|
||||
typedef struct persistence_config
|
||||
{
|
||||
int pathlen;
|
||||
char isopath[256];
|
||||
|
||||
int autosel;
|
||||
int cursel;
|
||||
int backendnum;
|
||||
file_fullpath *backendpath;
|
||||
@@ -596,24 +763,141 @@ typedef struct persistence_config
|
||||
struct persistence_config *next;
|
||||
}persistence_config;
|
||||
|
||||
#define vtoy_alias_image_file 0
|
||||
#define vtoy_alias_directory 1
|
||||
|
||||
typedef struct menu_alias
|
||||
{
|
||||
int type;
|
||||
int pathlen;
|
||||
char isopath[256];
|
||||
char alias[256];
|
||||
|
||||
struct menu_alias *next;
|
||||
}menu_alias;
|
||||
|
||||
#define vtoy_class_image_file 0
|
||||
#define vtoy_class_directory 1
|
||||
|
||||
typedef struct menu_class
|
||||
{
|
||||
int type;
|
||||
int patlen;
|
||||
char pattern[256];
|
||||
char class[64];
|
||||
|
||||
struct menu_class *next;
|
||||
}menu_class;
|
||||
|
||||
#define vtoy_max_replace_file_size (2 * 1024 * 1024)
|
||||
typedef struct conf_replace
|
||||
{
|
||||
int pathlen;
|
||||
char isopath[256];
|
||||
char orgconf[256];
|
||||
char newconf[256];
|
||||
|
||||
struct conf_replace *next;
|
||||
}conf_replace;
|
||||
|
||||
typedef struct injection_config
|
||||
{
|
||||
int pathlen;
|
||||
char isopath[256];
|
||||
char archive[256];
|
||||
|
||||
struct injection_config *next;
|
||||
}injection_config;
|
||||
|
||||
typedef struct auto_memdisk
|
||||
{
|
||||
int pathlen;
|
||||
char isopath[256];
|
||||
|
||||
struct auto_memdisk *next;
|
||||
}auto_memdisk;
|
||||
|
||||
typedef struct image_list
|
||||
{
|
||||
int pathlen;
|
||||
char isopath[256];
|
||||
|
||||
struct image_list *next;
|
||||
}image_list;
|
||||
|
||||
extern int g_ventoy_menu_esc;
|
||||
extern int g_ventoy_suppress_esc;
|
||||
extern int g_ventoy_last_entry;
|
||||
extern int g_ventoy_memdisk_mode;
|
||||
extern int g_ventoy_iso_raw;
|
||||
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;
|
||||
extern int g_plugin_image_list;
|
||||
extern ventoy_gpt_info *g_ventoy_part_info;
|
||||
extern grub_uint64_t g_conf_replace_offset;
|
||||
extern conf_replace *g_conf_replace_node;
|
||||
extern grub_uint8_t *g_conf_replace_new_buf;
|
||||
extern int g_conf_replace_new_len;
|
||||
extern int g_conf_replace_new_len_align;
|
||||
|
||||
#define ventoy_unix_fill_virt(new_data, new_len) \
|
||||
{ \
|
||||
data_secs = (new_len + 2047) / 2048; \
|
||||
cur->mem_sector_start = sector; \
|
||||
cur->mem_sector_end = cur->mem_sector_start + data_secs; \
|
||||
cur->mem_sector_offset = offset; \
|
||||
cur->remap_sector_start = 0; \
|
||||
cur->remap_sector_end = 0; \
|
||||
cur->org_sector_start = 0; \
|
||||
grub_memcpy(override + offset, new_data, new_len); \
|
||||
cur++; \
|
||||
sector += data_secs; \
|
||||
offset += new_len; \
|
||||
chain->virt_img_size_in_bytes += data_secs * 2048; \
|
||||
}
|
||||
|
||||
char * ventoy_get_line(char *start);
|
||||
int ventoy_cmp_img(img_info *img1, img_info *img2);
|
||||
void ventoy_swap_img(img_info *img1, img_info *img2);
|
||||
char * ventoy_plugin_get_cur_install_template(const char *isopath);
|
||||
install_template * ventoy_plugin_find_install_template(const char *isopath);
|
||||
persistence_config * ventoy_plugin_find_persistent(const char *isopath);
|
||||
void ventoy_plugin_dump_injection(void);
|
||||
void ventoy_plugin_dump_auto_install(void);
|
||||
int ventoy_fill_windows_rtdata(void *buf, char *isopath);
|
||||
int ventoy_plugin_get_persistent_chunklist(const char *isopath, int index, ventoy_img_chunk_list *chunk_list);
|
||||
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_plugin_get_image_list_index(int type, const char *name);
|
||||
conf_replace * ventoy_plugin_find_conf_replace(const char *iso);
|
||||
dud * ventoy_plugin_find_dud(const char *iso);
|
||||
int ventoy_plugin_load_dud(dud *node, const char *isopart);
|
||||
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_plugin_check_json(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_linux_get_main_initrd_index(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_collect_wim_patch(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_wim_patch_count(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_locate_wim_patch(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_unix_chain_data(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
int ventoy_get_disk_guid(const char *filename, grub_uint8_t *guid, grub_uint8_t *signature);
|
||||
grub_err_t ventoy_cmd_unix_reset(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_unix_replace_conf(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
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);
|
||||
grub_err_t ventoy_cmd_raw_chain_data(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_get_vtoy_type(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
|
||||
#endif /* __VENTOY_DEF_H__ */
|
||||
|
||||
|
@@ -42,6 +42,11 @@ static void json_debug(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
if (g_ventoy_debug == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
va_start (args, fmt);
|
||||
grub_vprintf (fmt, args);
|
||||
va_end (args);
|
||||
|
@@ -38,8 +38,7 @@
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
|
||||
static char * ventoy_get_line(char *start)
|
||||
char * ventoy_get_line(char *start)
|
||||
{
|
||||
if (start == NULL)
|
||||
{
|
||||
@@ -334,6 +333,7 @@ end:
|
||||
static grub_err_t ventoy_grub_cfg_initrd_collect(const char *fileName)
|
||||
{
|
||||
int i = 0;
|
||||
int dollar = 0;
|
||||
grub_file_t file = NULL;
|
||||
char *buf = NULL;
|
||||
char *start = NULL;
|
||||
@@ -389,13 +389,18 @@ static grub_err_t ventoy_grub_cfg_initrd_collect(const char *fileName)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
dollar = 0;
|
||||
for (i = 0; i < 255 && (0 == ventoy_is_word_end(*start)); i++)
|
||||
{
|
||||
img->name[i] = *start++;
|
||||
if (img->name[i] == '$')
|
||||
{
|
||||
dollar = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ventoy_find_initrd_by_name(g_initrd_img_list, img->name))
|
||||
if (dollar == 1 || ventoy_find_initrd_by_name(g_initrd_img_list, img->name))
|
||||
{
|
||||
grub_free(img);
|
||||
}
|
||||
@@ -565,6 +570,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;
|
||||
@@ -618,9 +631,30 @@ int ventoy_cpio_newc_fill_head(void *buf, int filesize, const void *filedata, co
|
||||
return headlen;
|
||||
}
|
||||
|
||||
static grub_uint32_t ventoy_linux_get_virt_chunk_count(void)
|
||||
{
|
||||
grub_uint32_t count = g_valid_initrd_count;
|
||||
|
||||
if (g_conf_replace_offset > 0)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static grub_uint32_t ventoy_linux_get_virt_chunk_size(void)
|
||||
{
|
||||
return (sizeof(ventoy_virt_chunk) + g_ventoy_cpio_size) * g_valid_initrd_count;
|
||||
grub_uint32_t size;
|
||||
|
||||
size = (sizeof(ventoy_virt_chunk) + g_ventoy_cpio_size) * g_valid_initrd_count;
|
||||
|
||||
if (g_conf_replace_offset > 0)
|
||||
{
|
||||
size += sizeof(ventoy_virt_chunk) + g_conf_replace_new_len_align;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static void ventoy_linux_fill_virt_data( grub_uint64_t isosize, ventoy_chain_head *chain)
|
||||
@@ -639,7 +673,7 @@ static void ventoy_linux_fill_virt_data( grub_uint64_t isosize, ventoy_chain_
|
||||
sector = (isosize + 2047) / 2048;
|
||||
cpio_secs = g_ventoy_cpio_size / 2048;
|
||||
|
||||
offset = g_valid_initrd_count * sizeof(ventoy_virt_chunk);
|
||||
offset = ventoy_linux_get_virt_chunk_count() * sizeof(ventoy_virt_chunk);
|
||||
cur = (ventoy_virt_chunk *)override;
|
||||
|
||||
for (node = g_initrd_img_list; node; node = node->next)
|
||||
@@ -675,12 +709,51 @@ static void ventoy_linux_fill_virt_data( grub_uint64_t isosize, ventoy_chain_
|
||||
cur++;
|
||||
}
|
||||
|
||||
if (g_conf_replace_offset > 0)
|
||||
{
|
||||
cpio_secs = g_conf_replace_new_len_align / 2048;
|
||||
|
||||
cur->mem_sector_start = sector;
|
||||
cur->mem_sector_end = cur->mem_sector_start + cpio_secs;
|
||||
cur->mem_sector_offset = offset;
|
||||
cur->remap_sector_start = 0;
|
||||
cur->remap_sector_end = 0;
|
||||
cur->org_sector_start = 0;
|
||||
|
||||
grub_memcpy(override + offset, g_conf_replace_new_buf, g_conf_replace_new_len);
|
||||
|
||||
chain->virt_img_size_in_bytes += g_conf_replace_new_len_align;
|
||||
|
||||
offset += g_conf_replace_new_len_align;
|
||||
sector += cpio_secs;
|
||||
cur++;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static grub_uint32_t ventoy_linux_get_override_chunk_count(void)
|
||||
{
|
||||
grub_uint32_t count = g_valid_initrd_count;
|
||||
|
||||
if (g_conf_replace_offset > 0)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static grub_uint32_t ventoy_linux_get_override_chunk_size(void)
|
||||
{
|
||||
return sizeof(ventoy_override_chunk) * g_valid_initrd_count;
|
||||
int count = g_valid_initrd_count;
|
||||
|
||||
if (g_conf_replace_offset > 0)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
return sizeof(ventoy_override_chunk) * count;
|
||||
}
|
||||
|
||||
static void ventoy_linux_fill_override_data( grub_uint64_t isosize, void *override)
|
||||
@@ -690,6 +763,8 @@ static void ventoy_linux_fill_override_data( grub_uint64_t isosize, void *ove
|
||||
grub_uint32_t newlen;
|
||||
grub_uint64_t sector;
|
||||
ventoy_override_chunk *cur;
|
||||
ventoy_iso9660_override *dirent;
|
||||
ventoy_udf_override *udf;
|
||||
|
||||
sector = (isosize + 2047) / 2048;
|
||||
|
||||
@@ -705,12 +780,12 @@ static void ventoy_linux_fill_override_data( grub_uint64_t isosize, void *ove
|
||||
mod = newlen % 4;
|
||||
if (mod > 0)
|
||||
{
|
||||
newlen += 4 - mod;
|
||||
newlen += 4 - mod; /* cpio must align with 4 */
|
||||
}
|
||||
|
||||
if (node->iso_type == 0)
|
||||
{
|
||||
ventoy_iso9660_override *dirent = (ventoy_iso9660_override *)node->override_data;
|
||||
dirent = (ventoy_iso9660_override *)node->override_data;
|
||||
|
||||
node->override_length = sizeof(ventoy_iso9660_override);
|
||||
dirent->first_sector = (grub_uint32_t)sector;
|
||||
@@ -722,7 +797,7 @@ static void ventoy_linux_fill_override_data( grub_uint64_t isosize, void *ove
|
||||
}
|
||||
else
|
||||
{
|
||||
ventoy_udf_override *udf = (ventoy_udf_override *)node->override_data;
|
||||
udf = (ventoy_udf_override *)node->override_data;
|
||||
|
||||
node->override_length = sizeof(ventoy_udf_override);
|
||||
udf->length = newlen;
|
||||
@@ -737,6 +812,23 @@ static void ventoy_linux_fill_override_data( grub_uint64_t isosize, void *ove
|
||||
cur++;
|
||||
}
|
||||
|
||||
if (g_conf_replace_offset > 0)
|
||||
{
|
||||
cur->img_offset = g_conf_replace_offset;
|
||||
cur->override_size = sizeof(ventoy_iso9660_override);
|
||||
|
||||
newlen = (grub_uint32_t)(g_conf_replace_new_len);
|
||||
|
||||
dirent = (ventoy_iso9660_override *)cur->override_data;
|
||||
dirent->first_sector = (grub_uint32_t)sector;
|
||||
dirent->size = newlen;
|
||||
dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector);
|
||||
dirent->size_be = grub_swap_bytes32(dirent->size);
|
||||
|
||||
sector += (dirent->size + 2047) / 2048;
|
||||
cur++;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -841,6 +933,50 @@ static grub_err_t ventoy_linux_locate_initrd(int filt, int *filtcnt)
|
||||
}
|
||||
|
||||
|
||||
grub_err_t ventoy_cmd_linux_get_main_initrd_index(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
int index = 0;
|
||||
char buf[32];
|
||||
initrd_info *node = NULL;
|
||||
|
||||
(void)ctxt;
|
||||
(void)argc;
|
||||
(void)args;
|
||||
|
||||
if (argc != 1)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (g_initrd_img_count == 1)
|
||||
{
|
||||
ventoy_set_env(args[0], "0");
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
||||
for (node = g_initrd_img_list; node; node = node->next)
|
||||
{
|
||||
if (node->size <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strstr(node->name, "ucode") || grub_strstr(node->name, "-firmware"))
|
||||
{
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
|
||||
grub_snprintf(buf, sizeof(buf), "%d", index);
|
||||
ventoy_set_env(args[0], buf);
|
||||
break;
|
||||
}
|
||||
|
||||
debug("main initrd index:%d\n", index);
|
||||
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_linux_locate_initrd(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
int sizefilt = 0;
|
||||
@@ -859,12 +995,65 @@ grub_err_t ventoy_cmd_linux_locate_initrd(grub_extcmd_context_t ctxt, int argc,
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
||||
static int ventoy_cpio_busybox64(cpio_newc_header *head)
|
||||
{
|
||||
char *name;
|
||||
int namelen;
|
||||
int offset;
|
||||
int count = 0;
|
||||
|
||||
name = (char *)(head + 1);
|
||||
while (name[0] && count < 2)
|
||||
{
|
||||
if (grub_strcmp(name, "ventoy/busybox/ash") == 0)
|
||||
{
|
||||
grub_memcpy(name, "ventoy/busybox/32h", 18);
|
||||
count++;
|
||||
}
|
||||
else if (grub_strcmp(name, "ventoy/busybox/64h") == 0)
|
||||
{
|
||||
grub_memcpy(name, "ventoy/busybox/ash", 18);
|
||||
count++;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
grub_err_t ventoy_cmd_cpio_busybox_64(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
(void)ctxt;
|
||||
(void)argc;
|
||||
(void)args;
|
||||
|
||||
debug("ventoy_cmd_busybox_64 %d\n", argc);
|
||||
ventoy_cpio_busybox64((cpio_newc_header *)g_ventoy_cpio_buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
grub_err_t ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
int i;
|
||||
int rc;
|
||||
char *pos = NULL;
|
||||
char *template_file = NULL;
|
||||
char *template_buf = NULL;
|
||||
char *persistent_buf = NULL;
|
||||
char *injection_buf = NULL;
|
||||
dud *dudnode = NULL;
|
||||
char tmpname[128];
|
||||
const char *injection_file = NULL;
|
||||
grub_uint8_t *buf = NULL;
|
||||
grub_uint32_t mod;
|
||||
grub_uint32_t headlen;
|
||||
@@ -873,14 +1062,16 @@ grub_err_t ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **arg
|
||||
grub_uint32_t img_chunk_size;
|
||||
grub_uint32_t template_size = 0;
|
||||
grub_uint32_t persistent_size = 0;
|
||||
grub_uint32_t injection_size = 0;
|
||||
grub_uint32_t dud_size = 0;
|
||||
grub_file_t file;
|
||||
grub_file_t scriptfile;
|
||||
grub_file_t tmpfile;
|
||||
ventoy_img_chunk_list chunk_list;
|
||||
|
||||
(void)ctxt;
|
||||
(void)argc;
|
||||
|
||||
if (argc != 3)
|
||||
if (argc != 4)
|
||||
{
|
||||
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s cpiofile\n", cmd_raw_name);
|
||||
}
|
||||
@@ -916,18 +1107,18 @@ grub_err_t ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **arg
|
||||
if (template_file)
|
||||
{
|
||||
debug("auto install template: <%s>\n", template_file);
|
||||
scriptfile = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", args[2], template_file);
|
||||
if (scriptfile)
|
||||
tmpfile = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", args[2], template_file);
|
||||
if (tmpfile)
|
||||
{
|
||||
debug("auto install script size %d\n", (int)scriptfile->size);
|
||||
template_size = scriptfile->size;
|
||||
debug("auto install script size %d\n", (int)tmpfile->size);
|
||||
template_size = tmpfile->size;
|
||||
template_buf = grub_malloc(template_size);
|
||||
if (template_buf)
|
||||
{
|
||||
grub_file_read(scriptfile, template_buf, template_size);
|
||||
grub_file_read(tmpfile, template_buf, template_size);
|
||||
}
|
||||
|
||||
grub_file_close(scriptfile);
|
||||
grub_file_close(tmpfile);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -939,11 +1130,57 @@ grub_err_t ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **arg
|
||||
debug("auto install script skipped or not configed %s\n", args[1]);
|
||||
}
|
||||
|
||||
g_ventoy_cpio_buf = grub_malloc(file->size + 4096 + template_size + persistent_size + img_chunk_size);
|
||||
injection_file = ventoy_plugin_get_injection(args[1]);
|
||||
if (injection_file)
|
||||
{
|
||||
debug("injection archive: <%s>\n", injection_file);
|
||||
tmpfile = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", args[2], injection_file);
|
||||
if (tmpfile)
|
||||
{
|
||||
debug("injection archive size:%d\n", (int)tmpfile->size);
|
||||
injection_size = tmpfile->size;
|
||||
injection_buf = grub_malloc(injection_size);
|
||||
if (injection_buf)
|
||||
{
|
||||
grub_file_read(tmpfile, injection_buf, injection_size);
|
||||
}
|
||||
|
||||
grub_file_close(tmpfile);
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("Failed to open injection archive %s%s\n", args[2], injection_file);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("injection not configed %s\n", args[1]);
|
||||
}
|
||||
|
||||
dudnode = ventoy_plugin_find_dud(args[1]);
|
||||
if (dudnode)
|
||||
{
|
||||
debug("dud file: <%d>\n", dudnode->dudnum);
|
||||
ventoy_plugin_load_dud(dudnode, args[2]);
|
||||
for (i = 0; i < dudnode->dudnum; i++)
|
||||
{
|
||||
if (dudnode->files[i].size > 0)
|
||||
{
|
||||
dud_size += dudnode->files[i].size + sizeof(cpio_newc_header);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("dud not configed %s\n", args[1]);
|
||||
}
|
||||
|
||||
g_ventoy_cpio_buf = grub_malloc(file->size + 40960 + template_size +
|
||||
persistent_size + injection_size + dud_size + img_chunk_size);
|
||||
if (NULL == g_ventoy_cpio_buf)
|
||||
{
|
||||
grub_file_close(file);
|
||||
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Can't alloc memory %llu\n", file->size + 4096 + img_chunk_size);
|
||||
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Can't alloc memory %llu\n", file->size);
|
||||
}
|
||||
|
||||
grub_file_read(file, g_ventoy_cpio_buf, file->size);
|
||||
@@ -976,6 +1213,27 @@ grub_err_t ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **arg
|
||||
persistent_buf = NULL;
|
||||
}
|
||||
|
||||
if (injection_size > 0 && injection_buf)
|
||||
{
|
||||
headlen = ventoy_cpio_newc_fill_head(buf, injection_size, injection_buf, "ventoy/ventoy_injection");
|
||||
buf += headlen + ventoy_align(injection_size, 4);
|
||||
|
||||
grub_free(injection_buf);
|
||||
injection_buf = NULL;
|
||||
}
|
||||
|
||||
if (dud_size > 0)
|
||||
{
|
||||
for (i = 0; i < dudnode->dudnum; i++)
|
||||
{
|
||||
pos = grub_strrchr(dudnode->dudpath[i].path, '.');
|
||||
grub_snprintf(tmpname, sizeof(tmpname), "ventoy/ventoy_dud%d%s", i, (pos ? pos : ".iso"));
|
||||
dud_size = dudnode->files[i].size;
|
||||
headlen = ventoy_cpio_newc_fill_head(buf, dud_size, dudnode->files[i].buf, tmpname);
|
||||
buf += headlen + ventoy_align(dud_size, 4);
|
||||
}
|
||||
}
|
||||
|
||||
/* step2: insert os param to cpio */
|
||||
headlen = ventoy_cpio_newc_fill_head(buf, 0, NULL, "ventoy/ventoy_os_param");
|
||||
padlen = sizeof(ventoy_os_param);
|
||||
@@ -997,6 +1255,102 @@ grub_err_t ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **arg
|
||||
|
||||
grub_file_close(file);
|
||||
|
||||
if (grub_strcmp(args[3], "busybox=64") == 0)
|
||||
{
|
||||
debug("cpio busybox proc %s\n", args[3]);
|
||||
ventoy_cpio_busybox64((cpio_newc_header *)g_ventoy_cpio_buf);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -1008,7 +1362,9 @@ grub_err_t ventoy_cmd_linux_chain_data(grub_extcmd_context_t ctxt, int argc, cha
|
||||
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_count = 0;
|
||||
grub_uint32_t virt_chunk_size = 0;
|
||||
grub_file_t file;
|
||||
grub_disk_t disk;
|
||||
@@ -1061,6 +1417,9 @@ grub_err_t ventoy_cmd_linux_chain_data(grub_extcmd_context_t ctxt, int argc, cha
|
||||
}
|
||||
|
||||
img_chunk_size = g_img_chunk_list.cur_chunk * sizeof(ventoy_img_chunk);
|
||||
|
||||
override_count = ventoy_linux_get_override_chunk_count();
|
||||
virt_chunk_count = ventoy_linux_get_virt_chunk_count();
|
||||
|
||||
if (ventoy_compatible)
|
||||
{
|
||||
@@ -1100,6 +1459,7 @@ grub_err_t ventoy_cmd_linux_chain_data(grub_extcmd_context_t ctxt, int argc, cha
|
||||
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 */
|
||||
@@ -1126,20 +1486,21 @@ grub_err_t ventoy_cmd_linux_chain_data(grub_extcmd_context_t ctxt, int argc, cha
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (g_valid_initrd_count == 0)
|
||||
/* part 4: override chunk */
|
||||
if (override_count > 0)
|
||||
{
|
||||
return 0;
|
||||
chain->override_chunk_offset = chain->img_chunk_offset + img_chunk_size;
|
||||
chain->override_chunk_num = override_count;
|
||||
ventoy_linux_fill_override_data(isosize, (char *)chain + chain->override_chunk_offset);
|
||||
}
|
||||
|
||||
/* part 4: override chunk */
|
||||
chain->override_chunk_offset = chain->img_chunk_offset + img_chunk_size;
|
||||
chain->override_chunk_num = g_valid_initrd_count;
|
||||
ventoy_linux_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 = g_valid_initrd_count;
|
||||
ventoy_linux_fill_virt_data(isosize, chain);
|
||||
if (virt_chunk_count > 0)
|
||||
{
|
||||
chain->virt_chunk_offset = chain->override_chunk_offset + override_size;
|
||||
chain->virt_chunk_num = virt_chunk_count;
|
||||
ventoy_linux_fill_virt_data(isosize, chain);
|
||||
}
|
||||
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
633
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_unix.c
Normal file
@@ -0,0 +1,633 @@
|
||||
/******************************************************************************
|
||||
* ventoy_unix.c
|
||||
*
|
||||
* Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#include <grub/types.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/device.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/partition.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/datetime.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/net.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/ventoy.h>
|
||||
#include "ventoy_def.h"
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
char g_ko_mod_path[256];
|
||||
int g_conf_new_len = 0;
|
||||
char *g_conf_new_data = NULL;
|
||||
|
||||
int g_mod_new_len = 0;
|
||||
char *g_mod_new_data = NULL;
|
||||
|
||||
grub_uint64_t g_mod_override_offset = 0;
|
||||
grub_uint64_t g_conf_override_offset = 0;
|
||||
|
||||
static int ventoy_get_file_override(const char *filename, grub_uint64_t *offset)
|
||||
{
|
||||
grub_file_t file;
|
||||
|
||||
*offset = 0;
|
||||
|
||||
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "(loop)%s", filename);
|
||||
if (!file)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
*offset = grub_iso9660_get_last_file_dirent_pos(file) + 2;
|
||||
|
||||
grub_file_close(file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_uint32_t ventoy_unix_get_override_chunk_count(void)
|
||||
{
|
||||
grub_uint32_t count = 0;
|
||||
|
||||
if (g_conf_new_len > 0)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
if (g_mod_new_len > 0)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static grub_uint32_t ventoy_unix_get_virt_chunk_count(void)
|
||||
{
|
||||
grub_uint32_t count = 0;
|
||||
|
||||
if (g_conf_new_len > 0)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
if (g_mod_new_len > 0)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
static grub_uint32_t ventoy_unix_get_virt_chunk_size(void)
|
||||
{
|
||||
grub_uint32_t size;
|
||||
|
||||
size = sizeof(ventoy_virt_chunk) * ventoy_unix_get_virt_chunk_count();
|
||||
|
||||
if (g_conf_new_len > 0)
|
||||
{
|
||||
size += ventoy_align_2k(g_conf_new_len);
|
||||
}
|
||||
|
||||
if (g_mod_new_len > 0)
|
||||
{
|
||||
size += ventoy_align_2k(g_mod_new_len);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static void ventoy_unix_fill_override_data( grub_uint64_t isosize, void *override)
|
||||
{
|
||||
grub_uint64_t sector;
|
||||
ventoy_override_chunk *cur;
|
||||
ventoy_iso9660_override *dirent;
|
||||
|
||||
sector = (isosize + 2047) / 2048;
|
||||
|
||||
cur = (ventoy_override_chunk *)override;
|
||||
|
||||
if (g_conf_new_len > 0)
|
||||
{
|
||||
/* loader.conf */
|
||||
cur->img_offset = g_conf_override_offset;
|
||||
cur->override_size = sizeof(ventoy_iso9660_override);
|
||||
dirent = (ventoy_iso9660_override *)cur->override_data;
|
||||
dirent->first_sector = (grub_uint32_t)sector;
|
||||
dirent->size = (grub_uint32_t)g_conf_new_len;
|
||||
dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector);
|
||||
dirent->size_be = grub_swap_bytes32(dirent->size);
|
||||
sector += (dirent->size + 2047) / 2048;
|
||||
}
|
||||
|
||||
if (g_mod_new_len > 0)
|
||||
{
|
||||
/* mod.ko */
|
||||
cur++;
|
||||
cur->img_offset = g_mod_override_offset;
|
||||
cur->override_size = sizeof(ventoy_iso9660_override);
|
||||
dirent = (ventoy_iso9660_override *)cur->override_data;
|
||||
dirent->first_sector = (grub_uint32_t)sector;
|
||||
dirent->size = (grub_uint32_t)g_mod_new_len;
|
||||
dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector);
|
||||
dirent->size_be = grub_swap_bytes32(dirent->size);
|
||||
sector += (dirent->size + 2047) / 2048;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void ventoy_unix_fill_virt_data( grub_uint64_t isosize, ventoy_chain_head *chain)
|
||||
{
|
||||
grub_uint64_t sector;
|
||||
grub_uint32_t offset;
|
||||
grub_uint32_t data_secs;
|
||||
char *override;
|
||||
ventoy_virt_chunk *cur;
|
||||
|
||||
override = (char *)chain + chain->virt_chunk_offset;
|
||||
cur = (ventoy_virt_chunk *)override;
|
||||
|
||||
sector = (isosize + 2047) / 2048;
|
||||
offset = 2 * sizeof(ventoy_virt_chunk);
|
||||
|
||||
if (g_conf_new_len > 0)
|
||||
{
|
||||
ventoy_unix_fill_virt(g_conf_new_data, g_conf_new_len);
|
||||
}
|
||||
|
||||
if (g_mod_new_len > 0)
|
||||
{
|
||||
ventoy_unix_fill_virt(g_mod_new_data, g_mod_new_len);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int ventoy_freebsd_append_conf(char *buf, const char *isopath)
|
||||
{
|
||||
int pos = 0;
|
||||
grub_uint32_t i;
|
||||
grub_disk_t disk;
|
||||
grub_file_t isofile;
|
||||
char uuid[64] = {0};
|
||||
ventoy_img_chunk *chunk;
|
||||
grub_uint8_t disk_sig[4];
|
||||
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, disk_sig);
|
||||
|
||||
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.disksignature=%02x%02x%02x%02x\n", disk_sig[0], disk_sig[1], disk_sig[2], disk_sig[3]);
|
||||
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);
|
||||
}
|
||||
|
559
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_vhd.c
Normal file
@@ -0,0 +1,559 @@
|
||||
/******************************************************************************
|
||||
* 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 grub_uint64_t g_img_trim_head_secnum = 0;
|
||||
|
||||
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(ventoy_patch_vhd *patch1, ventoy_patch_vhd *patch2)
|
||||
{
|
||||
char efipart[16] = {0};
|
||||
|
||||
grub_memcpy(efipart, g_ventoy_part_info->Head.Signature, sizeof(g_ventoy_part_info->Head.Signature));
|
||||
|
||||
debug("part1 type: 0x%x <%s>\n", g_ventoy_part_info->MBR.PartTbl[0].FsFlag, efipart);
|
||||
|
||||
if (grub_strncmp(efipart, "EFI PART", 8) == 0)
|
||||
{
|
||||
ventoy_debug_dump_guid("GPT disk GUID: ", g_ventoy_part_info->Head.DiskGuid);
|
||||
ventoy_debug_dump_guid("GPT part GUID: ", g_ventoy_part_info->PartTbl[0].PartGuid);
|
||||
|
||||
grub_memcpy(patch1->disk_signature_or_guid, g_ventoy_part_info->Head.DiskGuid, 16);
|
||||
grub_memcpy(patch1->part_offset_or_guid, g_ventoy_part_info->PartTbl[0].PartGuid, 16);
|
||||
grub_memcpy(patch2->disk_signature_or_guid, g_ventoy_part_info->Head.DiskGuid, 16);
|
||||
grub_memcpy(patch2->part_offset_or_guid, g_ventoy_part_info->PartTbl[0].PartGuid, 16);
|
||||
|
||||
patch1->part_type = patch2->part_type = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("MBR disk signature: %02x%02x%02x%02x\n",
|
||||
g_ventoy_part_info->MBR.BootCode[0x1b8 + 0], g_ventoy_part_info->MBR.BootCode[0x1b8 + 1],
|
||||
g_ventoy_part_info->MBR.BootCode[0x1b8 + 2], g_ventoy_part_info->MBR.BootCode[0x1b8 + 3]);
|
||||
grub_memcpy(patch1->disk_signature_or_guid, g_ventoy_part_info->MBR.BootCode + 0x1b8, 4);
|
||||
grub_memcpy(patch2->disk_signature_or_guid, g_ventoy_part_info->MBR.BootCode + 0x1b8, 4);
|
||||
}
|
||||
|
||||
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>\n", args[0]);
|
||||
|
||||
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(patch1, patch2);
|
||||
ventoy_vhd_patch_path(args[0], 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_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;
|
||||
}
|
||||
|
||||
static int ventoy_raw_trim_head(grub_uint64_t offset)
|
||||
{
|
||||
grub_uint32_t i;
|
||||
grub_uint32_t memsize;
|
||||
grub_uint32_t imgstart = 0;
|
||||
grub_uint32_t imgsecs = 0;
|
||||
grub_uint64_t sectors = 0;
|
||||
grub_uint64_t cursecs = 0;
|
||||
grub_uint64_t delta = 0;
|
||||
|
||||
if ((!g_img_chunk_list.chunk) || (!offset))
|
||||
{
|
||||
debug("image chunk not ready %p %lu\n", g_img_chunk_list.chunk, (ulong)offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
debug("image trim head %lu\n", (ulong)offset);
|
||||
|
||||
for (i = 0; i < g_img_chunk_list.cur_chunk; i++)
|
||||
{
|
||||
cursecs = g_img_chunk_list.chunk[i].disk_end_sector + 1 - g_img_chunk_list.chunk[i].disk_start_sector;
|
||||
sectors += cursecs;
|
||||
if (sectors >= offset)
|
||||
{
|
||||
delta = cursecs - (sectors - offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sectors < offset || i >= g_img_chunk_list.cur_chunk)
|
||||
{
|
||||
debug("Invalid size %lu %lu\n", (ulong)sectors, (ulong)offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sectors == offset)
|
||||
{
|
||||
memsize = (g_img_chunk_list.cur_chunk - (i + 1)) * sizeof(ventoy_img_chunk);
|
||||
grub_memmove(g_img_chunk_list.chunk, g_img_chunk_list.chunk + i + 1, memsize);
|
||||
g_img_chunk_list.cur_chunk -= (i + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_img_chunk_list.chunk[i].disk_start_sector += delta;
|
||||
g_img_chunk_list.chunk[i].img_start_sector += (grub_uint32_t)(delta / 4);
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
memsize = (g_img_chunk_list.cur_chunk - i) * sizeof(ventoy_img_chunk);
|
||||
grub_memmove(g_img_chunk_list.chunk, g_img_chunk_list.chunk + i, memsize);
|
||||
g_img_chunk_list.cur_chunk -= i;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < g_img_chunk_list.cur_chunk; i++)
|
||||
{
|
||||
imgsecs = g_img_chunk_list.chunk[i].img_end_sector + 1 - g_img_chunk_list.chunk[i].img_start_sector;
|
||||
g_img_chunk_list.chunk[i].img_start_sector = imgstart;
|
||||
g_img_chunk_list.chunk[i].img_end_sector = imgstart + (imgsecs - 1);
|
||||
imgstart += imgsecs;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_get_vtoy_type(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
int i;
|
||||
int offset = -1;
|
||||
grub_file_t file;
|
||||
vhd_footer_t vhdfoot;
|
||||
VDIPREHEADER vdihdr;
|
||||
char type[16] = {0};
|
||||
ventoy_gpt_info *gpt;
|
||||
|
||||
(void)ctxt;
|
||||
|
||||
g_img_trim_head_secnum = 0;
|
||||
|
||||
if (argc != 4)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
file = grub_file_open(args[0], VENTOY_FILE_TYPE);
|
||||
if (!file)
|
||||
{
|
||||
debug("Failed to open file %s\n", args[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_snprintf(type, sizeof(type), "unknown");
|
||||
|
||||
grub_file_seek(file, file->size - 512);
|
||||
grub_file_read(file, &vhdfoot, sizeof(vhdfoot));
|
||||
|
||||
if (grub_strncmp(vhdfoot.cookie, "conectix", 8) == 0)
|
||||
{
|
||||
offset = 0;
|
||||
grub_snprintf(type, sizeof(type), "vhd%u", grub_swap_bytes32(vhdfoot.disktype));
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_file_seek(file, 0);
|
||||
grub_file_read(file, &vdihdr, sizeof(vdihdr));
|
||||
if (vdihdr.u32Signature == VDI_IMAGE_SIGNATURE &&
|
||||
grub_strncmp(vdihdr.szFileInfo, VDI_IMAGE_FILE_INFO, grub_strlen(VDI_IMAGE_FILE_INFO)) == 0)
|
||||
{
|
||||
offset = 2 * 1048576;
|
||||
g_img_trim_head_secnum = offset / 512;
|
||||
grub_snprintf(type, sizeof(type), "vdi");
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = 0;
|
||||
grub_snprintf(type, sizeof(type), "raw");
|
||||
}
|
||||
}
|
||||
|
||||
grub_env_set(args[1], type);
|
||||
debug("<%s> vtoy type: <%s> ", args[0], type);
|
||||
|
||||
if (offset >= 0)
|
||||
{
|
||||
gpt = grub_zalloc(sizeof(ventoy_gpt_info));
|
||||
if (!gpt)
|
||||
{
|
||||
grub_env_set(args[1], "unknown");
|
||||
goto end;
|
||||
}
|
||||
|
||||
grub_file_seek(file, offset);
|
||||
grub_file_read(file, gpt, sizeof(ventoy_gpt_info));
|
||||
|
||||
if (gpt->MBR.Byte55 != 0x55 || gpt->MBR.ByteAA != 0xAA)
|
||||
{
|
||||
grub_env_set(args[1], "unknown");
|
||||
debug("invalid mbr signature: 0x%x 0x%x\n", gpt->MBR.Byte55, gpt->MBR.ByteAA);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (grub_memcmp(gpt->Head.Signature, "EFI PART", 8) == 0)
|
||||
{
|
||||
grub_env_set(args[2], "gpt");
|
||||
debug("part type: %s\n", "GPT");
|
||||
|
||||
if (gpt->MBR.PartTbl[0].FsFlag == 0xEE)
|
||||
{
|
||||
for (i = 0; i < 128; i++)
|
||||
{
|
||||
if (grub_memcmp(gpt->PartTbl[i].PartType, "Hah!IdontNeedEFI", 16) == 0)
|
||||
{
|
||||
debug("part %d is grub_bios part\n", i);
|
||||
grub_env_set(args[3], "1");
|
||||
break;
|
||||
}
|
||||
else if (gpt->PartTbl[i].LastLBA == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_env_set(args[2], "mbr");
|
||||
debug("part type: %s\n", "MBR");
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
if (gpt->MBR.PartTbl[i].FsFlag == 0xEF)
|
||||
{
|
||||
debug("part %d is esp part in MBR mode\n", i);
|
||||
grub_env_set(args[3], "1");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("part type: %s\n", "xxx");
|
||||
}
|
||||
|
||||
end:
|
||||
grub_check_free(gpt);
|
||||
grub_file_close(file);
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_raw_chain_data(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
grub_uint32_t size = 0;
|
||||
grub_uint32_t img_chunk_size = 0;
|
||||
grub_file_t file;
|
||||
grub_disk_t disk;
|
||||
const char *pLastChain = NULL;
|
||||
ventoy_chain_head *chain;
|
||||
char envbuf[64];
|
||||
|
||||
(void)ctxt;
|
||||
(void)argc;
|
||||
|
||||
if (NULL == g_img_chunk_list.chunk)
|
||||
{
|
||||
grub_printf("ventoy not ready\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (g_img_trim_head_secnum > 0)
|
||||
{
|
||||
ventoy_raw_trim_head(g_img_trim_head_secnum);
|
||||
}
|
||||
|
||||
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
|
||||
if (!file)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
img_chunk_size = g_img_chunk_list.cur_chunk * sizeof(ventoy_img_chunk);
|
||||
|
||||
size = sizeof(ventoy_chain_head) + img_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_env_export("vtoy_chain_mem_addr");
|
||||
grub_env_export("vtoy_chain_mem_size");
|
||||
|
||||
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;
|
||||
if (g_img_trim_head_secnum > 0)
|
||||
{
|
||||
chain->real_img_size_in_bytes -= g_img_trim_head_secnum * 512;
|
||||
}
|
||||
|
||||
chain->virt_img_size_in_bytes = chain->real_img_size_in_bytes;
|
||||
chain->boot_catalog = 0;
|
||||
|
||||
/* 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);
|
||||
|
||||
grub_file_seek(file, g_img_trim_head_secnum * 512);
|
||||
grub_file_read(file, chain->boot_catalog_sector, 512);
|
||||
|
||||
grub_file_close(file);
|
||||
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
157
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/xpress.c
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Xpress Compression Algorithm (MS-XCA) decompression
|
||||
*
|
||||
*/
|
||||
|
||||
#include "wimboot.h"
|
||||
#include "huffman.h"
|
||||
#include "xpress.h"
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wcast-align"
|
||||
|
||||
/**
|
||||
* Decompress XCA-compressed data
|
||||
*
|
||||
* @v data Compressed data
|
||||
* @v len Length of compressed data
|
||||
* @v buf Decompression buffer, or NULL
|
||||
* @ret out_len Length of decompressed data, or negative error
|
||||
*/
|
||||
ssize_t xca_decompress ( const void *data, size_t len, void *buf ) {
|
||||
const void *src = data;
|
||||
const void *end = ( uint8_t * ) src + len;
|
||||
uint8_t *out = buf;
|
||||
size_t out_len = 0;
|
||||
size_t out_len_threshold = 0;
|
||||
const struct xca_huf_len *lengths;
|
||||
struct xca xca;
|
||||
uint32_t accum = 0;
|
||||
int extra_bits = 0;
|
||||
unsigned int huf;
|
||||
struct huffman_symbols *sym;
|
||||
unsigned int raw;
|
||||
unsigned int match_len;
|
||||
unsigned int match_offset_bits;
|
||||
unsigned int match_offset;
|
||||
const uint8_t *copy;
|
||||
int rc;
|
||||
|
||||
/* Process data stream */
|
||||
while ( src < end ) {
|
||||
|
||||
/* (Re)initialise decompressor if applicable */
|
||||
if ( out_len >= out_len_threshold ) {
|
||||
|
||||
/* Construct symbol lengths */
|
||||
lengths = src;
|
||||
src = ( uint8_t * ) src + sizeof ( *lengths );
|
||||
if ( src > end ) {
|
||||
DBG ( "XCA too short to hold Huffman lengths table.\n");
|
||||
return -1;
|
||||
}
|
||||
for ( raw = 0 ; raw < XCA_CODES ; raw++ )
|
||||
xca.lengths[raw] = xca_huf_len ( lengths, raw );
|
||||
|
||||
/* Construct Huffman alphabet */
|
||||
if ( ( rc = huffman_alphabet ( &xca.alphabet,
|
||||
xca.lengths,
|
||||
XCA_CODES ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Initialise state */
|
||||
accum = XCA_GET16 ( src );
|
||||
accum <<= 16;
|
||||
accum |= XCA_GET16 ( src );
|
||||
extra_bits = 16;
|
||||
|
||||
/* Determine next threshold */
|
||||
out_len_threshold = ( out_len + XCA_BLOCK_SIZE );
|
||||
}
|
||||
|
||||
/* Determine symbol */
|
||||
huf = ( accum >> ( 32 - HUFFMAN_BITS ) );
|
||||
sym = huffman_sym ( &xca.alphabet, huf );
|
||||
raw = huffman_raw ( sym, huf );
|
||||
accum <<= huffman_len ( sym );
|
||||
extra_bits -= huffman_len ( sym );
|
||||
if ( extra_bits < 0 ) {
|
||||
accum |= ( XCA_GET16 ( src ) << ( -extra_bits ) );
|
||||
extra_bits += 16;
|
||||
}
|
||||
|
||||
/* Process symbol */
|
||||
if ( raw < XCA_END_MARKER ) {
|
||||
|
||||
/* Literal symbol - add to output stream */
|
||||
if ( buf )
|
||||
*(out++) = raw;
|
||||
out_len++;
|
||||
|
||||
} else if ( ( raw == XCA_END_MARKER ) &&
|
||||
( (uint8_t *) src >= ( ( uint8_t * ) end - 1 ) ) ) {
|
||||
|
||||
/* End marker symbol */
|
||||
return out_len;
|
||||
|
||||
} else {
|
||||
|
||||
/* LZ77 match symbol */
|
||||
raw -= XCA_END_MARKER;
|
||||
match_offset_bits = ( raw >> 4 );
|
||||
match_len = ( raw & 0x0f );
|
||||
if ( match_len == 0x0f ) {
|
||||
match_len = XCA_GET8 ( src );
|
||||
if ( match_len == 0xff ) {
|
||||
match_len = XCA_GET16 ( src );
|
||||
} else {
|
||||
match_len += 0x0f;
|
||||
}
|
||||
}
|
||||
match_len += 3;
|
||||
if ( match_offset_bits ) {
|
||||
match_offset =
|
||||
( ( accum >> ( 32 - match_offset_bits ))
|
||||
+ ( 1 << match_offset_bits ) );
|
||||
} else {
|
||||
match_offset = 1;
|
||||
}
|
||||
accum <<= match_offset_bits;
|
||||
extra_bits -= match_offset_bits;
|
||||
if ( extra_bits < 0 ) {
|
||||
accum |= ( XCA_GET16 ( src ) << (-extra_bits) );
|
||||
extra_bits += 16;
|
||||
}
|
||||
|
||||
/* Copy data */
|
||||
out_len += match_len;
|
||||
if ( buf ) {
|
||||
copy = ( out - match_offset );
|
||||
while ( match_len-- )
|
||||
*(out++) = *(copy++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return out_len;
|
||||
}
|
87
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/xpress.h
Normal file
@@ -0,0 +1,87 @@
|
||||
#ifndef _XCA_H
|
||||
#define _XCA_H
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Xpress Compression Algorithm (MS-XCA) decompression
|
||||
*
|
||||
*/
|
||||
|
||||
#include "huffman.h"
|
||||
|
||||
/** Number of XCA codes */
|
||||
#define XCA_CODES 512
|
||||
|
||||
/** XCA decompressor */
|
||||
struct xca {
|
||||
/** Huffman alphabet */
|
||||
struct huffman_alphabet alphabet;
|
||||
/** Raw symbols
|
||||
*
|
||||
* Must immediately follow the Huffman alphabet.
|
||||
*/
|
||||
huffman_raw_symbol_t raw[XCA_CODES];
|
||||
/** Code lengths */
|
||||
uint8_t lengths[XCA_CODES];
|
||||
};
|
||||
|
||||
/** XCA symbol Huffman lengths table */
|
||||
struct xca_huf_len {
|
||||
/** Lengths of each symbol */
|
||||
uint8_t nibbles[ XCA_CODES / 2 ];
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/**
|
||||
* Extract Huffman-coded length of a raw symbol
|
||||
*
|
||||
* @v lengths Huffman lengths table
|
||||
* @v symbol Raw symbol
|
||||
* @ret len Huffman-coded length
|
||||
*/
|
||||
static inline unsigned int xca_huf_len ( const struct xca_huf_len *lengths,
|
||||
unsigned int symbol ) {
|
||||
return ( ( ( lengths->nibbles[ symbol / 2 ] ) >>
|
||||
( 4 * ( symbol % 2 ) ) ) & 0x0f );
|
||||
}
|
||||
|
||||
/** Get word from source data stream */
|
||||
#define XCA_GET16( src ) ( { \
|
||||
const uint16_t *src16 = src; \
|
||||
src = ( uint8_t * ) src + sizeof ( *src16 ); \
|
||||
*src16; } )
|
||||
|
||||
/** Get byte from source data stream */
|
||||
#define XCA_GET8( src ) ( { \
|
||||
const uint8_t *src8 = src; \
|
||||
src = ( uint8_t * ) src + sizeof ( *src8 ); \
|
||||
*src8; } )
|
||||
|
||||
/** XCA source data stream end marker */
|
||||
#define XCA_END_MARKER 256
|
||||
|
||||
/** XCA block size */
|
||||
#define XCA_BLOCK_SIZE ( 64 * 1024 )
|
||||
|
||||
extern ssize_t xca_decompress ( const void *data, size_t len, void *buf );
|
||||
|
||||
#endif /* _XCA_H */
|
53
GRUB2/MOD_SRC/grub-2.04/include/grub/compiler.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/* compiler.h - macros for various compiler features */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2002,2003,2005,2006,2007,2008,2009,2010,2014 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GRUB_COMPILER_HEADER
|
||||
#define GRUB_COMPILER_HEADER 1
|
||||
|
||||
/* GCC version checking borrowed from glibc. */
|
||||
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
|
||||
# define GNUC_PREREQ(maj,min) \
|
||||
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
|
||||
#else
|
||||
# define GNUC_PREREQ(maj,min) 0
|
||||
#endif
|
||||
|
||||
/* Does this compiler support compile-time error attributes? */
|
||||
#if GNUC_PREREQ(4,3)
|
||||
# define ATTRIBUTE_ERROR(msg) \
|
||||
__attribute__ ((__error__ (msg)))
|
||||
#else
|
||||
# define ATTRIBUTE_ERROR(msg) __attribute__ ((noreturn))
|
||||
#endif
|
||||
|
||||
#if GNUC_PREREQ(4,4)
|
||||
# define GNU_PRINTF gnu_printf
|
||||
#else
|
||||
# define GNU_PRINTF printf
|
||||
#endif
|
||||
|
||||
#if GNUC_PREREQ(3,4)
|
||||
# define WARN_UNUSED_RESULT __attribute__ ((warn_unused_result))
|
||||
#else
|
||||
# define WARN_UNUSED_RESULT
|
||||
#endif
|
||||
|
||||
#define UNUSED __attribute__((__unused__))
|
||||
|
||||
#endif /* ! GRUB_COMPILER_HEADER */
|
243
GRUB2/MOD_SRC/grub-2.04/include/grub/file.h
Normal file
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2002,2007 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GRUB_FILE_HEADER
|
||||
#define GRUB_FILE_HEADER 1
|
||||
|
||||
#include <grub/types.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/device.h>
|
||||
#include <grub/fs.h>
|
||||
#include <grub/disk.h>
|
||||
|
||||
enum grub_file_type
|
||||
{
|
||||
GRUB_FILE_TYPE_NONE = 0,
|
||||
/* GRUB module to be loaded. */
|
||||
GRUB_FILE_TYPE_GRUB_MODULE,
|
||||
/* Loopback file to be represented as disk. */
|
||||
GRUB_FILE_TYPE_LOOPBACK,
|
||||
/* Linux kernel to be loaded. */
|
||||
GRUB_FILE_TYPE_LINUX_KERNEL,
|
||||
/* Linux initrd. */
|
||||
GRUB_FILE_TYPE_LINUX_INITRD,
|
||||
|
||||
/* Multiboot kernel. */
|
||||
GRUB_FILE_TYPE_MULTIBOOT_KERNEL,
|
||||
/* Multiboot module. */
|
||||
GRUB_FILE_TYPE_MULTIBOOT_MODULE,
|
||||
|
||||
/* Xen hypervisor - used on ARM only. */
|
||||
GRUB_FILE_TYPE_XEN_HYPERVISOR,
|
||||
/* Xen module - used on ARM only. */
|
||||
GRUB_FILE_TYPE_XEN_MODULE,
|
||||
|
||||
GRUB_FILE_TYPE_BSD_KERNEL,
|
||||
GRUB_FILE_TYPE_FREEBSD_ENV,
|
||||
GRUB_FILE_TYPE_FREEBSD_MODULE,
|
||||
GRUB_FILE_TYPE_FREEBSD_MODULE_ELF,
|
||||
GRUB_FILE_TYPE_NETBSD_MODULE,
|
||||
GRUB_FILE_TYPE_OPENBSD_RAMDISK,
|
||||
|
||||
GRUB_FILE_TYPE_XNU_INFO_PLIST,
|
||||
GRUB_FILE_TYPE_XNU_MKEXT,
|
||||
GRUB_FILE_TYPE_XNU_KEXT,
|
||||
GRUB_FILE_TYPE_XNU_KERNEL,
|
||||
GRUB_FILE_TYPE_XNU_RAMDISK,
|
||||
GRUB_FILE_TYPE_XNU_HIBERNATE_IMAGE,
|
||||
GRUB_FILE_XNU_DEVPROP,
|
||||
|
||||
GRUB_FILE_TYPE_PLAN9_KERNEL,
|
||||
|
||||
GRUB_FILE_TYPE_NTLDR,
|
||||
GRUB_FILE_TYPE_TRUECRYPT,
|
||||
GRUB_FILE_TYPE_FREEDOS,
|
||||
GRUB_FILE_TYPE_PXECHAINLOADER,
|
||||
GRUB_FILE_TYPE_PCCHAINLOADER,
|
||||
|
||||
GRUB_FILE_TYPE_COREBOOT_CHAINLOADER,
|
||||
|
||||
GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE,
|
||||
|
||||
/* File holding signature. */
|
||||
GRUB_FILE_TYPE_SIGNATURE,
|
||||
/* File holding public key to verify signature once. */
|
||||
GRUB_FILE_TYPE_PUBLIC_KEY,
|
||||
/* File holding public key to add to trused keys. */
|
||||
GRUB_FILE_TYPE_PUBLIC_KEY_TRUST,
|
||||
/* File of which we intend to print a blocklist to the user. */
|
||||
GRUB_FILE_TYPE_PRINT_BLOCKLIST,
|
||||
/* File we intend to use for test loading or testing speed. */
|
||||
GRUB_FILE_TYPE_TESTLOAD,
|
||||
/* File we open only to get its size. E.g. in ls output. */
|
||||
GRUB_FILE_TYPE_GET_SIZE,
|
||||
/* Font file. */
|
||||
GRUB_FILE_TYPE_FONT,
|
||||
/* File holding encryption key for encrypted ZFS. */
|
||||
GRUB_FILE_TYPE_ZFS_ENCRYPTION_KEY,
|
||||
/* File we open n grub-fstest. */
|
||||
GRUB_FILE_TYPE_FSTEST,
|
||||
/* File we open n grub-mount. */
|
||||
GRUB_FILE_TYPE_MOUNT,
|
||||
/* File which we attempt to identify the type of. */
|
||||
GRUB_FILE_TYPE_FILE_ID,
|
||||
/* File holding ACPI table. */
|
||||
GRUB_FILE_TYPE_ACPI_TABLE,
|
||||
/* File holding Device Tree. */
|
||||
GRUB_FILE_TYPE_DEVICE_TREE_IMAGE,
|
||||
/* File we intend show to user. */
|
||||
GRUB_FILE_TYPE_CAT,
|
||||
GRUB_FILE_TYPE_HEXCAT,
|
||||
/* One of pair of files we intend to compare. */
|
||||
GRUB_FILE_TYPE_CMP,
|
||||
/* List of hashes for hashsum. */
|
||||
GRUB_FILE_TYPE_HASHLIST,
|
||||
/* File hashed by hashsum. */
|
||||
GRUB_FILE_TYPE_TO_HASH,
|
||||
/* Keyboard layout. */
|
||||
GRUB_FILE_TYPE_KEYBOARD_LAYOUT,
|
||||
/* Picture file. */
|
||||
GRUB_FILE_TYPE_PIXMAP,
|
||||
/* *.lst shipped by GRUB. */
|
||||
GRUB_FILE_TYPE_GRUB_MODULE_LIST,
|
||||
/* config file. */
|
||||
GRUB_FILE_TYPE_CONFIG,
|
||||
GRUB_FILE_TYPE_THEME,
|
||||
GRUB_FILE_TYPE_GETTEXT_CATALOG,
|
||||
GRUB_FILE_TYPE_FS_SEARCH,
|
||||
GRUB_FILE_TYPE_AUDIO,
|
||||
GRUB_FILE_TYPE_VBE_DUMP,
|
||||
|
||||
GRUB_FILE_TYPE_LOADENV,
|
||||
GRUB_FILE_TYPE_SAVEENV,
|
||||
|
||||
GRUB_FILE_TYPE_VERIFY_SIGNATURE,
|
||||
|
||||
GRUB_FILE_TYPE_MASK = 0xffff,
|
||||
|
||||
/* --skip-sig is specified. */
|
||||
GRUB_FILE_TYPE_SKIP_SIGNATURE = 0x10000,
|
||||
GRUB_FILE_TYPE_NO_DECOMPRESS = 0x20000
|
||||
};
|
||||
|
||||
/* File description. */
|
||||
struct grub_file
|
||||
{
|
||||
/* File name. */
|
||||
char *name;
|
||||
|
||||
/* The underlying device. */
|
||||
grub_device_t device;
|
||||
|
||||
/* The underlying filesystem. */
|
||||
grub_fs_t fs;
|
||||
|
||||
/* The current offset. */
|
||||
grub_off_t offset;
|
||||
grub_off_t progress_offset;
|
||||
|
||||
/* Progress info. */
|
||||
grub_uint64_t last_progress_time;
|
||||
grub_off_t last_progress_offset;
|
||||
grub_uint64_t estimated_speed;
|
||||
|
||||
/* The file size. */
|
||||
grub_off_t size;
|
||||
|
||||
/* If file is not easily seekable. Should be set by underlying layer. */
|
||||
int not_easily_seekable;
|
||||
|
||||
/* Filesystem-specific data. */
|
||||
void *data;
|
||||
|
||||
/* This is called when a sector is read. Used only for a disk device. */
|
||||
grub_disk_read_hook_t read_hook;
|
||||
|
||||
/* Caller-specific data passed to the read hook. */
|
||||
void *read_hook_data;
|
||||
};
|
||||
typedef struct grub_file *grub_file_t;
|
||||
|
||||
extern grub_disk_read_hook_t EXPORT_VAR(grub_file_progress_hook);
|
||||
|
||||
/* Filters with lower ID are executed first. */
|
||||
typedef enum grub_file_filter_id
|
||||
{
|
||||
GRUB_FILE_FILTER_VERIFY,
|
||||
GRUB_FILE_FILTER_GZIO,
|
||||
GRUB_FILE_FILTER_XZIO,
|
||||
GRUB_FILE_FILTER_LZOPIO,
|
||||
GRUB_FILE_FILTER_MAX,
|
||||
GRUB_FILE_FILTER_COMPRESSION_FIRST = GRUB_FILE_FILTER_GZIO,
|
||||
GRUB_FILE_FILTER_COMPRESSION_LAST = GRUB_FILE_FILTER_LZOPIO,
|
||||
} grub_file_filter_id_t;
|
||||
|
||||
typedef grub_file_t (*grub_file_filter_t) (grub_file_t in, enum grub_file_type type);
|
||||
|
||||
extern grub_file_filter_t EXPORT_VAR(grub_file_filters)[GRUB_FILE_FILTER_MAX];
|
||||
|
||||
static inline void
|
||||
grub_file_filter_register (grub_file_filter_id_t id, grub_file_filter_t filter)
|
||||
{
|
||||
grub_file_filters[id] = filter;
|
||||
}
|
||||
|
||||
static inline void
|
||||
grub_file_filter_unregister (grub_file_filter_id_t id)
|
||||
{
|
||||
grub_file_filters[id] = 0;
|
||||
}
|
||||
|
||||
/* Get a device name from NAME. */
|
||||
char *EXPORT_FUNC(grub_file_get_device_name) (const char *name);
|
||||
|
||||
int EXPORT_FUNC(ventoy_check_file_exist) (const char * fmt, ...);
|
||||
grub_file_t EXPORT_FUNC(grub_file_open) (const char *name, enum grub_file_type type);
|
||||
grub_ssize_t EXPORT_FUNC(grub_file_read) (grub_file_t file, void *buf,
|
||||
grub_size_t len);
|
||||
grub_off_t EXPORT_FUNC(grub_file_seek) (grub_file_t file, grub_off_t offset);
|
||||
grub_err_t EXPORT_FUNC(grub_file_close) (grub_file_t file);
|
||||
|
||||
/* Return value of grub_file_size() in case file size is unknown. */
|
||||
#define GRUB_FILE_SIZE_UNKNOWN 0xffffffffffffffffULL
|
||||
|
||||
static inline grub_off_t
|
||||
grub_file_size (const grub_file_t file)
|
||||
{
|
||||
return file->size;
|
||||
}
|
||||
|
||||
static inline grub_off_t
|
||||
grub_file_tell (const grub_file_t file)
|
||||
{
|
||||
return file->offset;
|
||||
}
|
||||
|
||||
static inline int
|
||||
grub_file_seekable (const grub_file_t file)
|
||||
{
|
||||
return !file->not_easily_seekable;
|
||||
}
|
||||
|
||||
grub_file_t
|
||||
grub_file_offset_open (grub_file_t parent, enum grub_file_type type,
|
||||
grub_off_t start, grub_off_t size);
|
||||
void
|
||||
grub_file_offset_close (grub_file_t file);
|
||||
|
||||
#endif /* ! GRUB_FILE_HEADER */
|
133
GRUB2/MOD_SRC/grub-2.04/include/grub/kernel.h
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2002,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GRUB_KERNEL_HEADER
|
||||
#define GRUB_KERNEL_HEADER 1
|
||||
|
||||
#include <grub/types.h>
|
||||
#include <grub/symbol.h>
|
||||
|
||||
enum
|
||||
{
|
||||
OBJ_TYPE_ELF,
|
||||
OBJ_TYPE_MEMDISK,
|
||||
OBJ_TYPE_CONFIG,
|
||||
OBJ_TYPE_PREFIX,
|
||||
OBJ_TYPE_PUBKEY,
|
||||
OBJ_TYPE_DTB
|
||||
};
|
||||
|
||||
/* The module header. */
|
||||
struct grub_module_header
|
||||
{
|
||||
/* The type of object. */
|
||||
grub_uint32_t type;
|
||||
/* The size of object (including this header). */
|
||||
grub_uint32_t size;
|
||||
};
|
||||
|
||||
/* "gmim" (GRUB Module Info Magic). */
|
||||
#define GRUB_MODULE_MAGIC 0x676d696d
|
||||
|
||||
struct grub_module_info32
|
||||
{
|
||||
/* Magic number so we know we have modules present. */
|
||||
grub_uint32_t magic;
|
||||
/* The offset of the modules. */
|
||||
grub_uint32_t offset;
|
||||
/* The size of all modules plus this header. */
|
||||
grub_uint32_t size;
|
||||
};
|
||||
|
||||
struct grub_module_info64
|
||||
{
|
||||
/* Magic number so we know we have modules present. */
|
||||
grub_uint32_t magic;
|
||||
grub_uint32_t padding;
|
||||
/* The offset of the modules. */
|
||||
grub_uint64_t offset;
|
||||
/* The size of all modules plus this header. */
|
||||
grub_uint64_t size;
|
||||
};
|
||||
|
||||
#ifndef GRUB_UTIL
|
||||
/* Space isn't reusable on some platforms. */
|
||||
/* On Qemu the preload space is readonly. */
|
||||
/* On emu there is no preload space. */
|
||||
/* On ieee1275 our code assumes that heap is p=v which isn't guaranteed for module space. */
|
||||
#if defined (GRUB_MACHINE_QEMU) || defined (GRUB_MACHINE_EMU) \
|
||||
|| defined (GRUB_MACHINE_EFI) \
|
||||
|| (defined (GRUB_MACHINE_IEEE1275) && !defined (__sparc__))
|
||||
#define GRUB_KERNEL_PRELOAD_SPACE_REUSABLE 0
|
||||
#endif
|
||||
|
||||
#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) \
|
||||
|| defined (GRUB_MACHINE_MULTIBOOT) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS) \
|
||||
|| defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_ARC) \
|
||||
|| (defined (__sparc__) && defined (GRUB_MACHINE_IEEE1275)) \
|
||||
|| defined (GRUB_MACHINE_UBOOT) || defined (GRUB_MACHINE_XEN) \
|
||||
|| defined(GRUB_MACHINE_XEN_PVH)
|
||||
/* FIXME: stack is between 2 heap regions. Move it. */
|
||||
#define GRUB_KERNEL_PRELOAD_SPACE_REUSABLE 1
|
||||
#endif
|
||||
|
||||
#ifndef GRUB_KERNEL_PRELOAD_SPACE_REUSABLE
|
||||
#error "Please check if preload space is reusable on this platform!"
|
||||
#endif
|
||||
|
||||
#if GRUB_TARGET_SIZEOF_VOID_P == 8
|
||||
#define grub_module_info grub_module_info64
|
||||
#else
|
||||
#define grub_module_info grub_module_info32
|
||||
#endif
|
||||
|
||||
extern grub_addr_t EXPORT_VAR (grub_modbase);
|
||||
|
||||
void EXPORT_FUNC(ventoy_env_hook_root)(int hook);
|
||||
|
||||
#define FOR_MODULES(var) for (\
|
||||
var = (grub_modbase && ((((struct grub_module_info *) grub_modbase)->magic) == GRUB_MODULE_MAGIC)) ? (struct grub_module_header *) \
|
||||
(grub_modbase + (((struct grub_module_info *) grub_modbase)->offset)) : 0;\
|
||||
var && (grub_addr_t) var \
|
||||
< (grub_modbase + (((struct grub_module_info *) grub_modbase)->size)); \
|
||||
var = (struct grub_module_header *) \
|
||||
(((grub_uint32_t *) var) + ((((struct grub_module_header *) var)->size + sizeof (grub_addr_t) - 1) / sizeof (grub_addr_t)) * (sizeof (grub_addr_t) / sizeof (grub_uint32_t))))
|
||||
|
||||
grub_addr_t grub_modules_get_end (void);
|
||||
|
||||
#endif
|
||||
|
||||
/* The start point of the C code. */
|
||||
void grub_main (void) __attribute__ ((noreturn));
|
||||
|
||||
/* The machine-specific initialization. This must initialize memory. */
|
||||
void grub_machine_init (void);
|
||||
|
||||
/* The machine-specific finalization. */
|
||||
void EXPORT_FUNC(grub_machine_fini) (int flags);
|
||||
|
||||
/* The machine-specific prefix initialization. */
|
||||
void
|
||||
grub_machine_get_bootlocation (char **device, char **path);
|
||||
|
||||
/* Register all the exported symbols. This is automatically generated. */
|
||||
void grub_register_exported_symbols (void);
|
||||
|
||||
extern void (*EXPORT_VAR(grub_net_poll_cards_idle)) (void);
|
||||
|
||||
#endif /* ! GRUB_KERNEL_HEADER */
|
119
GRUB2/MOD_SRC/grub-2.04/include/grub/menu.h
Normal file
@@ -0,0 +1,119 @@
|
||||
/* menu.h - Menu model function prototypes and data structures. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GRUB_MENU_HEADER
|
||||
#define GRUB_MENU_HEADER 1
|
||||
|
||||
struct bls_entry
|
||||
{
|
||||
struct bls_entry *next;
|
||||
struct bls_entry *prev;
|
||||
struct keyval **keyvals;
|
||||
int nkeyvals;
|
||||
char *filename;
|
||||
int visible;
|
||||
};
|
||||
|
||||
struct grub_menu_entry_class
|
||||
{
|
||||
char *name;
|
||||
struct grub_menu_entry_class *next;
|
||||
};
|
||||
|
||||
/* The menu entry. */
|
||||
struct grub_menu_entry
|
||||
{
|
||||
/* The title name. */
|
||||
const char *title;
|
||||
|
||||
/* The identifier. */
|
||||
const char *id;
|
||||
|
||||
/* If set means not everybody is allowed to boot this entry. */
|
||||
int restricted;
|
||||
|
||||
/* Allowed users. */
|
||||
const char *users;
|
||||
|
||||
/* The classes associated with the menu entry:
|
||||
used to choose an icon or other style attributes.
|
||||
This is a dummy head node for the linked list, so for an entry E,
|
||||
E.classes->next is the first class if it is not NULL. */
|
||||
struct grub_menu_entry_class *classes;
|
||||
|
||||
/* The sourcecode of the menu entry, used by the editor. */
|
||||
const char *sourcecode;
|
||||
|
||||
/* Parameters to be passed to menu definition. */
|
||||
int argc;
|
||||
char **args;
|
||||
|
||||
int hotkey;
|
||||
|
||||
int submenu;
|
||||
|
||||
/* The next element. */
|
||||
struct grub_menu_entry *next;
|
||||
|
||||
/* BLS used to populate the entry */
|
||||
struct bls_entry *bls;
|
||||
};
|
||||
typedef struct grub_menu_entry *grub_menu_entry_t;
|
||||
|
||||
/* The menu. */
|
||||
struct grub_menu
|
||||
{
|
||||
/* The size of a menu. */
|
||||
int size;
|
||||
|
||||
/* The list of menu entries. */
|
||||
grub_menu_entry_t entry_list;
|
||||
};
|
||||
typedef struct grub_menu *grub_menu_t;
|
||||
|
||||
/* Callback structure menu viewers can use to provide user feedback when
|
||||
default entries are executed, possibly including fallback entries. */
|
||||
typedef struct grub_menu_execute_callback
|
||||
{
|
||||
/* Called immediately before ENTRY is booted. */
|
||||
void (*notify_booting) (grub_menu_entry_t entry, void *userdata);
|
||||
|
||||
/* Called when executing one entry has failed, and another entry, ENTRY, will
|
||||
be executed as a fallback. The implementation of this function should
|
||||
delay for a period of at least 2 seconds before returning in order to
|
||||
allow the user time to read the information before it can be lost by
|
||||
executing ENTRY. */
|
||||
void (*notify_fallback) (grub_menu_entry_t entry, void *userdata);
|
||||
|
||||
/* Called when an entry has failed to execute and there is no remaining
|
||||
fallback entry to attempt. */
|
||||
void (*notify_failure) (void *userdata);
|
||||
}
|
||||
*grub_menu_execute_callback_t;
|
||||
|
||||
grub_menu_entry_t grub_menu_get_entry (grub_menu_t menu, int no);
|
||||
int grub_menu_get_timeout (void);
|
||||
void grub_menu_set_timeout (int timeout);
|
||||
void grub_menu_entry_run (grub_menu_entry_t entry);
|
||||
int grub_menu_get_default_entry_index (grub_menu_t menu);
|
||||
|
||||
void grub_menu_init (void);
|
||||
void grub_menu_fini (void);
|
||||
|
||||
#endif /* GRUB_MENU_HEADER */
|
177
GRUB2/MOD_SRC/grub-2.04/include/grub/normal.h
Normal file
@@ -0,0 +1,177 @@
|
||||
/* normal.h - prototypes for the normal mode */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2002,2003,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GRUB_NORMAL_HEADER
|
||||
#define GRUB_NORMAL_HEADER 1
|
||||
|
||||
#include <grub/term.h>
|
||||
#include <grub/symbol.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/menu.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/file.h>
|
||||
|
||||
/* The standard left and right margin for some messages. */
|
||||
#define STANDARD_MARGIN 6
|
||||
|
||||
/* The type of a completion item. */
|
||||
enum grub_completion_type
|
||||
{
|
||||
GRUB_COMPLETION_TYPE_COMMAND,
|
||||
GRUB_COMPLETION_TYPE_DEVICE,
|
||||
GRUB_COMPLETION_TYPE_PARTITION,
|
||||
GRUB_COMPLETION_TYPE_FILE,
|
||||
GRUB_COMPLETION_TYPE_ARGUMENT
|
||||
};
|
||||
typedef enum grub_completion_type grub_completion_type_t;
|
||||
|
||||
extern struct grub_menu_viewer grub_normal_text_menu_viewer;
|
||||
extern int grub_normal_exit_level;
|
||||
|
||||
/* Defined in `main.c'. */
|
||||
void grub_enter_normal_mode (const char *config);
|
||||
void grub_normal_execute (const char *config, int nested, int batch);
|
||||
struct grub_term_screen_geometry
|
||||
{
|
||||
/* The number of entries shown at a time. */
|
||||
int num_entries;
|
||||
int first_entry_y;
|
||||
int first_entry_x;
|
||||
int entry_width;
|
||||
int timeout_y;
|
||||
int timeout_lines;
|
||||
int border;
|
||||
int right_margin;
|
||||
};
|
||||
|
||||
void grub_menu_init_page (int nested, int edit,
|
||||
struct grub_term_screen_geometry *geo,
|
||||
struct grub_term_output *term);
|
||||
void grub_normal_init_page (struct grub_term_output *term, int y);
|
||||
char *grub_file_getline (grub_file_t file);
|
||||
void grub_cmdline_run (int nested, int force_auth);
|
||||
|
||||
/* Defined in `cmdline.c'. */
|
||||
char *grub_cmdline_get (const char *prompt);
|
||||
grub_err_t grub_set_history (int newsize);
|
||||
|
||||
/* Defined in `completion.c'. */
|
||||
char *grub_normal_do_completion (char *buf, int *restore,
|
||||
void (*hook) (const char *item, grub_completion_type_t type, int count));
|
||||
|
||||
/* Defined in `misc.c'. */
|
||||
grub_err_t grub_normal_print_device_info (const char *name);
|
||||
|
||||
/* Defined in `color.c'. */
|
||||
char *grub_env_write_color_normal (struct grub_env_var *var, const char *val);
|
||||
char *grub_env_write_color_highlight (struct grub_env_var *var, const char *val);
|
||||
int grub_parse_color_name_pair (grub_uint8_t *ret, const char *name);
|
||||
|
||||
/* Defined in `menu_text.c'. */
|
||||
void grub_wait_after_message (void);
|
||||
void
|
||||
grub_print_ucs4 (const grub_uint32_t * str,
|
||||
const grub_uint32_t * last_position,
|
||||
int margin_left, int margin_right,
|
||||
struct grub_term_output *term);
|
||||
|
||||
void
|
||||
grub_print_ucs4_menu (const grub_uint32_t * str,
|
||||
const grub_uint32_t * last_position,
|
||||
int margin_left, int margin_right,
|
||||
struct grub_term_output *term,
|
||||
int skip_lines, int max_lines, grub_uint32_t contchar,
|
||||
struct grub_term_pos *pos);
|
||||
int
|
||||
grub_ucs4_count_lines (const grub_uint32_t * str,
|
||||
const grub_uint32_t * last_position,
|
||||
int margin_left, int margin_right,
|
||||
struct grub_term_output *term);
|
||||
grub_size_t grub_getstringwidth (grub_uint32_t * str,
|
||||
const grub_uint32_t * last_position,
|
||||
struct grub_term_output *term);
|
||||
void grub_print_message_indented (const char *msg, int margin_left,
|
||||
int margin_right,
|
||||
struct grub_term_output *term);
|
||||
void
|
||||
grub_menu_text_register_instances (int entry, grub_menu_t menu, int nested);
|
||||
grub_err_t
|
||||
grub_show_menu (grub_menu_t menu, int nested, int autobooted);
|
||||
|
||||
/* Defined in `handler.c'. */
|
||||
void read_handler_list (void);
|
||||
void free_handler_list (void);
|
||||
|
||||
/* Defined in `dyncmd.c'. */
|
||||
void read_command_list (const char *prefix);
|
||||
|
||||
/* Defined in `autofs.c'. */
|
||||
void read_fs_list (const char *prefix);
|
||||
|
||||
void grub_context_init (void);
|
||||
void grub_context_fini (void);
|
||||
|
||||
void read_crypto_list (const char *prefix);
|
||||
|
||||
void read_terminal_list (const char *prefix);
|
||||
|
||||
void grub_set_more (int onoff);
|
||||
|
||||
void grub_normal_reset_more (void);
|
||||
|
||||
void grub_xputs_normal (const char *str);
|
||||
|
||||
extern int grub_extractor_level;
|
||||
|
||||
grub_err_t
|
||||
grub_normal_add_menu_entry (int argc, const char **args, char **classes,
|
||||
const char *id,
|
||||
const char *users, const char *hotkey,
|
||||
const char *prefix, const char *sourcecode,
|
||||
int submenu, int *index, struct bls_entry *bls);
|
||||
|
||||
grub_err_t
|
||||
grub_normal_set_password (const char *user, const char *password);
|
||||
|
||||
void grub_normal_free_menu (grub_menu_t menu);
|
||||
|
||||
void grub_normal_auth_init (void);
|
||||
void grub_normal_auth_fini (void);
|
||||
|
||||
void
|
||||
grub_xnputs (const char *str, grub_size_t msg_len);
|
||||
|
||||
grub_command_t
|
||||
grub_dyncmd_get_cmd (grub_command_t cmd);
|
||||
|
||||
void
|
||||
grub_gettext_reread_prefix (const char *val);
|
||||
|
||||
enum grub_human_size_type
|
||||
{
|
||||
GRUB_HUMAN_SIZE_NORMAL,
|
||||
GRUB_HUMAN_SIZE_SHORT,
|
||||
GRUB_HUMAN_SIZE_SPEED,
|
||||
};
|
||||
|
||||
const char *
|
||||
grub_get_human_size (grub_uint64_t size, enum grub_human_size_type type);
|
||||
|
||||
#endif /* ! GRUB_NORMAL_HEADER */
|
@@ -40,6 +40,15 @@ typedef enum ventoy_fs_type
|
||||
ventoy_fs_max
|
||||
}ventoy_fs_type;
|
||||
|
||||
typedef enum ventoy_chain_type
|
||||
{
|
||||
ventoy_chain_linux = 0, /* 0: linux */
|
||||
ventoy_chain_windows, /* 1: windows */
|
||||
ventoy_chain_wim, /* 2: wim */
|
||||
|
||||
ventoy_chain_max
|
||||
}ventoy_chain_type;
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
typedef struct ventoy_guid
|
||||
@@ -62,7 +71,7 @@ typedef struct ventoy_image_location
|
||||
{
|
||||
ventoy_guid guid;
|
||||
|
||||
/* image sector size, currently this value is always 2048 */
|
||||
/* image sector size, 2048/512 */
|
||||
grub_uint32_t image_sector_size;
|
||||
|
||||
/* disk sector size, normally the value is 512 */
|
||||
@@ -109,18 +118,24 @@ typedef struct ventoy_os_param
|
||||
*
|
||||
* vtoy_reserved[0]: vtoy_break_level
|
||||
* vtoy_reserved[1]: vtoy_debug_level
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
grub_uint8_t vtoy_reserved[32]; // Internal use by ventoy
|
||||
|
||||
grub_uint8_t reserved[31];
|
||||
grub_uint8_t vtoy_disk_signature[4];
|
||||
|
||||
grub_uint8_t reserved[27];
|
||||
}ventoy_os_param;
|
||||
|
||||
|
||||
typedef struct ventoy_windows_data
|
||||
{
|
||||
char auto_install_script[384];
|
||||
grub_uint8_t reserved[128];
|
||||
char injection_archive[384];
|
||||
grub_uint8_t reserved[256];
|
||||
}ventoy_windows_data;
|
||||
|
||||
|
||||
@@ -201,12 +216,14 @@ typedef struct ventoy_img_chunk_list
|
||||
|
||||
#define ventoy_filt_register grub_file_filter_register
|
||||
|
||||
typedef const char * (*grub_env_get_pf)(const char *name);
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
#define GRUB_FILE_REPLACE_MAGIC 0x1258BEEF
|
||||
|
||||
typedef const char * (*grub_env_get_pf)(const char *name);
|
||||
typedef int (*grub_env_set_pf)(const char *name, const char *val);
|
||||
typedef int (*grub_env_printf_pf)(const char *fmt, ...);
|
||||
|
||||
typedef struct ventoy_grub_param_file_replace
|
||||
{
|
||||
grub_uint32_t magic;
|
||||
@@ -218,8 +235,9 @@ typedef struct ventoy_grub_param_file_replace
|
||||
typedef struct ventoy_grub_param
|
||||
{
|
||||
grub_env_get_pf grub_env_get;
|
||||
|
||||
grub_env_set_pf grub_env_set;
|
||||
ventoy_grub_param_file_replace file_replace;
|
||||
grub_env_printf_pf grub_env_printf;
|
||||
}ventoy_grub_param;
|
||||
|
||||
#pragma pack()
|
||||
@@ -227,6 +245,7 @@ typedef struct ventoy_grub_param
|
||||
|
||||
int grub_ext_get_file_chunk(grub_uint64_t part_start, grub_file_t file, ventoy_img_chunk_list *chunk_list);
|
||||
int grub_fat_get_file_chunk(grub_uint64_t part_start, grub_file_t file, ventoy_img_chunk_list *chunk_list);
|
||||
void grub_iso9660_set_nojoliet(int nojoliet);
|
||||
grub_uint64_t grub_iso9660_get_last_read_pos(grub_file_t file);
|
||||
grub_uint64_t grub_iso9660_get_last_file_dirent_pos(grub_file_t file);
|
||||
grub_uint64_t grub_udf_get_file_offset(grub_file_t file);
|
||||
|
@@ -12,18 +12,23 @@ make install
|
||||
PATH=$PATH:$VT_DIR/GRUB2/INSTALL/bin/:$VT_DIR/GRUB2/INSTALL/sbin/
|
||||
|
||||
net_modules_legacy="net tftp http"
|
||||
all_modules_legacy="date drivemap blocklist lspci pci ext2 xfs ventoy chain read halt iso9660 linux16 test true sleep reboot echo videotest videoinfo videotest_checksum video_colors video_cirrus video_bochs vga vbe video_fb font video gettext extcmd terminal linux minicmd help configfile tr trig boot biosdisk disk ls tar squash4 password_pbkdf2 all_video png jpeg part_msdos fat exfat ntfs loopback gzio normal udf gfxmenu gfxterm gfxterm_background gfxterm_menu"
|
||||
all_modules_legacy="date drivemap blocklist regexp newc vga_text ntldr search at_keyboard usb_keyboard gcry_md5 hashsum gzio xzio lzopio lspci pci ext2 xfs ventoy chain read halt iso9660 linux16 test true sleep reboot echo videotest videoinfo videotest_checksum video_colors video_cirrus video_bochs vga vbe video_fb font video gettext extcmd terminal linux minicmd help configfile tr trig boot biosdisk disk ls tar squash4 password_pbkdf2 all_video png jpeg part_gpt part_msdos fat exfat ntfs loopback gzio normal udf gfxmenu gfxterm gfxterm_background gfxterm_menu"
|
||||
|
||||
net_modules_uefi="efinet net tftp http"
|
||||
all_modules_uefi="blocklist ventoy test ext2 xfs read halt sleep serial terminfo png password_pbkdf2 gcry_sha512 pbkdf2 part_gpt part_msdos ls tar squash4 loopback part_apple minicmd diskfilter linux relocator jpeg iso9660 udf hfsplus halt acpi mmap gfxmenu video_colors trig bitmap_scale gfxterm bitmap font fat exfat ntfs fshelp efifwsetup reboot echo configfile normal terminal gettext chain priority_queue bufio datetime cat extcmd crypto gzio boot all_video efi_gop efi_uga video_bochs video_cirrus video video_fb gfxterm_background gfxterm_menu"
|
||||
|
||||
all_modules_uefi="blocklist ventoy test regexp newc search at_keyboard usb_keyboard gcry_md5 hashsum gzio xzio lzopio ext2 xfs read halt sleep serial terminfo png password_pbkdf2 gcry_sha512 pbkdf2 part_gpt part_msdos ls tar squash4 loopback part_apple minicmd diskfilter linux relocator jpeg iso9660 udf hfsplus halt acpi mmap gfxmenu video_colors trig bitmap_scale gfxterm bitmap font fat exfat ntfs fshelp efifwsetup reboot echo configfile normal terminal gettext chain priority_queue bufio datetime cat extcmd crypto gzio boot all_video efi_gop efi_uga video_bochs video_cirrus video video_fb gfxterm_background gfxterm_menu"
|
||||
|
||||
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 '(,msdos2)/grub' --output "$VT_DIR/INSTALL/EFI/BOOT/grubx64_real.efi" --format 'x86_64-efi' --compression 'auto' $all_modules_uefi 'fat' 'part_msdos'
|
||||
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 '(,msdos2)/grub' --output "$VT_DIR/INSTALL/grub/i386-pc/core.img" --format 'i386-pc' --compression 'auto' $all_modules_legacy 'fat' 'part_msdos' 'biosdisk'
|
||||
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
|
||||
@@ -33,11 +38,29 @@ if [ "$1" = "uefi" ]; then
|
||||
cp -a $VT_DIR/GRUB2/PXE/grub2/x86_64-efi/core.efi $VT_DIR/GRUB2/NBP/core.efi || exit 1
|
||||
|
||||
rm -f $VT_DIR/INSTALL/grub/x86_64-efi/normal.mod
|
||||
cp -a $VT_DIR/GRUB2/PXE/grub2/x86_64-efi/normal.mod $VT_DIR/INSTALL/grub/x86_64-efi/normal.mod || exit 1
|
||||
cp -a $VT_DIR/GRUB2/PXE/grub2/x86_64-efi/normal.mod $VT_DIR/INSTALL/grub/x86_64-efi/normal.mod || exit 1
|
||||
|
||||
#copy other modules
|
||||
ls -1 $VT_DIR/GRUB2/INSTALL/lib/grub/x86_64-efi/ | egrep '\.(lst|mod)$' | while read line; do
|
||||
if ! echo $all_modules | grep -q " ${line%.mod} "; then
|
||||
echo "Copy $line ..."
|
||||
rm -f $VT_DIR/INSTALL/grub/x86_64-efi/$line
|
||||
cp -a $VT_DIR/GRUB2/INSTALL/lib/grub/x86_64-efi/$line $VT_DIR/INSTALL/grub/x86_64-efi/
|
||||
fi
|
||||
done
|
||||
else
|
||||
rm -f $VT_DIR/GRUB2/NBP/core.0
|
||||
cp -a $VT_DIR/GRUB2/PXE/grub2/i386-pc/core.0 $VT_DIR/GRUB2/NBP/core.0 || exit 1
|
||||
|
||||
rm -f $VT_DIR/INSTALL/grub/i386-pc/boot.img
|
||||
cp -a $VT_DIR/GRUB2/INSTALL/lib/grub/i386-pc/boot.img $VT_DIR/INSTALL/grub/i386-pc/boot.img || exit 1
|
||||
|
||||
#copy other modules
|
||||
ls -1 $VT_DIR/GRUB2/INSTALL/lib/grub/i386-pc/ | egrep '\.(lst|mod)$' | while read line; do
|
||||
if ! echo $all_modules | grep -q " ${line%.mod} "; then
|
||||
echo "Copy $line ..."
|
||||
rm -f $VT_DIR/INSTALL/grub/i386-pc/$line
|
||||
cp -a $VT_DIR/GRUB2/INSTALL/lib/grub/i386-pc/$line $VT_DIR/INSTALL/grub/i386-pc/
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
BIN
ICON/forums.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
ICON/logo_128.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
ICON/logo_16.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
ICON/logo_256.png
Normal file
After Width: | Height: | Size: 76 KiB |
BIN
ICON/logo_32.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
ICON/logo_48.png
Normal file
After Width: | Height: | Size: 5.3 KiB |
BIN
ICON/logo_512.png
Normal file
After Width: | Height: | Size: 223 KiB |
BIN
ICON/logo_64.png
Normal file
After Width: | Height: | Size: 7.7 KiB |
BIN
ICON/logo_72.png
Normal file
After Width: | Height: | Size: 9.0 KiB |
@@ -1,4 +1,4 @@
|
||||
#!/ventoy/busybox/tmpsh
|
||||
#!/ventoy/busybox/ash
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
@@ -36,8 +36,25 @@ export SED=$BUSYBOX_PATH/sed
|
||||
export SLEEP=$BUSYBOX_PATH/sleep
|
||||
export HEAD=$BUSYBOX_PATH/head
|
||||
|
||||
$BUSYBOX_PATH/tmpxz -d $BUSYBOX_PATH/busybox.xz
|
||||
$BUSYBOX_PATH/busybox --install $BUSYBOX_PATH
|
||||
if [ -e $BUSYBOX_PATH/64h ]; then
|
||||
$BUSYBOX_PATH/xzminidec32 < $BUSYBOX_PATH/busybox32.xz > $BUSYBOX_PATH/busybox
|
||||
$BUSYBOX_PATH/vtchmod32 $BUSYBOX_PATH/busybox
|
||||
else
|
||||
$BUSYBOX_PATH/xzminidec64 < $BUSYBOX_PATH/busybox64.xz > $BUSYBOX_PATH/busybox
|
||||
if [ -s $BUSYBOX_PATH/busybox ]; then
|
||||
$BUSYBOX_PATH/vtchmod64 $BUSYBOX_PATH/busybox
|
||||
else
|
||||
$BUSYBOX_PATH/xzminidec64_uclibc < $BUSYBOX_PATH/busybox64.xz > $BUSYBOX_PATH/busybox
|
||||
$BUSYBOX_PATH/vtchmod64_uclibc $BUSYBOX_PATH/busybox
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -e $BUSYBOX_PATH/busybox ]; then
|
||||
$BUSYBOX_PATH/busybox --install $BUSYBOX_PATH
|
||||
else
|
||||
$BUSYBOX_PATH/tmpxz -d $BUSYBOX_PATH/busybox32.xz
|
||||
$BUSYBOX_PATH/busybox32 --install $BUSYBOX_PATH
|
||||
fi
|
||||
|
||||
export PATH=$BUSYBOX_PATH/:$VTOY_PATH/tool
|
||||
|
||||
@@ -54,14 +71,29 @@ 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
|
||||
xz -d -c tool.cpio.xz | cpio -idm
|
||||
xz -d -c loop.cpio.xz | cpio -idm
|
||||
else
|
||||
xz -d -c hook.cpio.xz | cpio -idm 2>>$VTLOG
|
||||
xz -d -c tool.cpio.xz | cpio -idm 2>>$VTLOG
|
||||
xz -d -c loop.cpio.xz | cpio -idm 2>>$VTLOG
|
||||
fi
|
||||
|
||||
if [ -e $BUSYBOX_PATH/64h ]; then
|
||||
echo "Use busybox32 toolkit ..." >>$VTLOG
|
||||
ln -s $BUSYBOX_PATH/xzminidec32 $BUSYBOX_PATH/xzminidec
|
||||
ln -s $VTOY_PATH/tool/dmsetup32 $VTOY_PATH/tool/dmsetup
|
||||
ln -s $VTOY_PATH/tool/lunzip32 $VTOY_PATH/tool/lunzip
|
||||
else
|
||||
echo "Use busybox64 toolkit ..." >>$VTLOG
|
||||
ln -s $BUSYBOX_PATH/xzminidec64 $BUSYBOX_PATH/xzminidec
|
||||
ln -s $VTOY_PATH/tool/dmsetup64 $VTOY_PATH/tool/dmsetup
|
||||
ln -s $VTOY_PATH/tool/lunzip64 $VTOY_PATH/tool/lunzip
|
||||
fi
|
||||
|
||||
rm -f *.xz
|
||||
|
BIN
IMG/cpio/ventoy/busybox/64h
Normal file
BIN
IMG/cpio/ventoy/busybox/busybox64.xz
Normal file
BIN
IMG/cpio/ventoy/busybox/vtchmod32
Normal file
BIN
IMG/cpio/ventoy/busybox/vtchmod64
Normal file
BIN
IMG/cpio/ventoy/busybox/vtchmod64_uclibc
Normal file
BIN
IMG/cpio/ventoy/busybox/xzminidec64
Normal file
BIN
IMG/cpio/ventoy/busybox/xzminidec64_uclibc
Normal file
43
IMG/cpio/ventoy/hook/adelie/disk-hook.sh
Normal file
@@ -0,0 +1,43 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. /ventoy/hook/ventoy-hook-lib.sh
|
||||
|
||||
if is_ventoy_hook_finished; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
vtlog "####### $0 $* ########"
|
||||
|
||||
VTPATH_OLD=$PATH; PATH=$BUSYBOX_PATH:$VTOY_PATH/tool:$PATH
|
||||
|
||||
wait_for_usb_disk_ready
|
||||
|
||||
vtdiskname=$(get_ventoy_disk_name)
|
||||
if [ "$vtdiskname" = "unknown" ]; then
|
||||
vtlog "ventoy disk not found"
|
||||
PATH=$VTPATH_OLD
|
||||
exit 0
|
||||
fi
|
||||
|
||||
ventoy_udev_disk_common_hook "${vtdiskname#/dev/}2" "noreplace"
|
||||
|
||||
PATH=$VTPATH_OLD
|
||||
|
||||
set_ventoy_hook_finish
|
23
IMG/cpio/ventoy/hook/adelie/ventoy-hook.sh
Normal file
@@ -0,0 +1,23 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. $VTOY_PATH/hook/ventoy-os-lib.sh
|
||||
|
||||
$VTOY_PATH/hook/adelie/disk-hook.sh &
|
||||
|
@@ -59,7 +59,15 @@ mkdir -p $VTOY_PATH/mnt
|
||||
mount /vt_modloop $VTOY_PATH/mnt
|
||||
|
||||
KoModPath=$(find $VTOY_PATH/mnt/ -name 'dm-mod.ko*')
|
||||
vtlog "insmod $KoModPath"
|
||||
vtlog "KoModPath=$KoModPath"
|
||||
|
||||
if modinfo $KoModPath | grep -q 'depend.*dax'; then
|
||||
vtlog "First install dax mod ..."
|
||||
DaxModPath=$(echo $KoModPath | sed 's#md/dm-mod#dax/dax#')
|
||||
vtlog "insmod $DaxModPath"
|
||||
insmod $DaxModPath
|
||||
fi
|
||||
|
||||
insmod $KoModPath
|
||||
|
||||
umount $VTOY_PATH/mnt
|
||||
|
@@ -32,13 +32,14 @@ fi
|
||||
|
||||
#
|
||||
# We do a trick for ATL series here.
|
||||
# Use /dev/loop7 and wapper it as a cdrom with bind mount.
|
||||
# Then the installer will accept /dev/loop7 as the install medium.
|
||||
# Use /dev/vtCheatLoop and wapper it as a cdrom with bind mount.
|
||||
# Then the installer will accept /dev/vtCheatLoop as the install medium.
|
||||
#
|
||||
ventoy_copy_device_mapper /dev/loop7
|
||||
$BUSYBOX_PATH/mkdir -p /tmp/loop7/device/
|
||||
echo 5 > /tmp/loop7/device/type
|
||||
$BUSYBOX_PATH/mount --bind /tmp/loop7 /sys/block/loop7 >> $VTLOG 2>&1
|
||||
vtCheatLoop=loop6
|
||||
ventoy_copy_device_mapper /dev/$vtCheatLoop
|
||||
$BUSYBOX_PATH/mkdir -p /tmp/$vtCheatLoop/device/
|
||||
echo 5 > /tmp/$vtCheatLoop/device/type
|
||||
$BUSYBOX_PATH/mount --bind /tmp/$vtCheatLoop /sys/block/$vtCheatLoop >> $VTLOG 2>&1
|
||||
|
||||
|
||||
# OK finish
|
||||
|
50
IMG/cpio/ventoy/hook/arch/ovios-disk.sh
Normal file
@@ -0,0 +1,50 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. /ventoy/hook/ventoy-hook-lib.sh
|
||||
|
||||
vtlog "######### $0 $* ############"
|
||||
|
||||
VTPATH_OLD=$PATH; PATH=$BUSYBOX_PATH:$VTOY_PATH/tool:$PATH
|
||||
|
||||
wait_for_usb_disk_ready
|
||||
|
||||
vtdiskname=$(get_ventoy_disk_name)
|
||||
if [ "$vtdiskname" = "unknown" ]; then
|
||||
vtlog "ventoy disk not found"
|
||||
PATH=$VTPATH_OLD
|
||||
exit 0
|
||||
fi
|
||||
|
||||
ventoy_udev_disk_common_hook "${vtdiskname#/dev/}2" "noreplace"
|
||||
|
||||
blkdev_num=$($VTOY_PATH/tool/dmsetup ls | grep ventoy | sed 's/.*(\([0-9][0-9]*\),.*\([0-9][0-9]*\).*/\1:\2/')
|
||||
blkdev_num_mknod=$($VTOY_PATH/tool/dmsetup ls | grep ventoy | sed 's/.*(\([0-9][0-9]*\),.*\([0-9][0-9]*\).*/\1 \2/')
|
||||
vtDM=$(ventoy_find_dm_id ${blkdev_num})
|
||||
|
||||
vtlog "blkdev_num=$blkdev_num blkdev_num_mknod=$blkdev_num_mknod vtDM=$vtDM"
|
||||
|
||||
if [ -b /dev/$vtDM ]; then
|
||||
vtlog "dev already exist ..."
|
||||
else
|
||||
vtlog "mknode dev ..."
|
||||
mknod -m 660 /dev/$vtDM b $blkdev_num_mknod
|
||||
fi
|
||||
|
||||
PATH=$VTPATH_OLD
|
@@ -35,14 +35,32 @@ fi
|
||||
|
||||
ventoy_udev_disk_common_hook "${vtdiskname#/dev/}2" "noreplace"
|
||||
|
||||
blkdev_num=$($VTOY_PATH/tool/dmsetup ls | grep ventoy | sed 's/.*(\([0-9][0-9]*\),.*\([0-9][0-9]*\).*/\1:\2/')
|
||||
vtDM=$(ventoy_find_dm_id ${blkdev_num})
|
||||
vtlog "blkdev_num=$blkdev_num vtDM=$vtDM ..."
|
||||
|
||||
while [ -n "Y" ]; do
|
||||
if [ -b /dev/$vtDM ]; then
|
||||
break
|
||||
else
|
||||
sleep 0.3
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -n "$1" ]; then
|
||||
blkdev_num=$($VTOY_PATH/tool/dmsetup ls | grep ventoy | sed 's/.*(\([0-9][0-9]*\),.*\([0-9][0-9]*\).*/\1:\2/')
|
||||
vtDM=$(ventoy_find_dm_id ${blkdev_num})
|
||||
|
||||
vtlog "ln -s /dev/$vtDM $1"
|
||||
ln -s /dev/$vtDM "$1"
|
||||
else
|
||||
vtLABEL=$($BUSYBOX_PATH/blkid /dev/$vtDM | $SED 's/.*LABEL="\([^"]*\)".*/\1/')
|
||||
vtlog "vtLABEL is $vtLABEL"
|
||||
|
||||
if [ -z "$vtLABEL" ]; then
|
||||
vtLABEL=$($SED "s/.*label=\([^ ]*\)/\1/" /proc/cmdline)
|
||||
vtlog "vtLABEL is $vtLABEL from cmdline"
|
||||
fi
|
||||
|
||||
ln -s /dev/$vtDM "/dev/disk/by-label/$vtLABEL"
|
||||
fi
|
||||
|
||||
# OK finish
|
||||
set_ventoy_hook_finish
|
||||
|
||||
|
@@ -21,11 +21,31 @@
|
||||
|
||||
if $GREP -q '^"$mount_handler"' /init; then
|
||||
echo 'use mount_handler ...' >> $VTLOG
|
||||
$SED "/^\"\$mount_handler\"/i\ $BUSYBOX_PATH/sh $VTOY_PATH/hook/arch/ventoy-disk.sh \"\$archisodevice\"" -i /init
|
||||
|
||||
if [ -f /hooks/archiso ]; then
|
||||
$SED '/while ! poll_device "${dev}"/a\ if /ventoy/busybox/sh /ventoy/hook/arch/ventoy-timeout.sh ${dev}; then break; fi' -i /hooks/archiso
|
||||
vthookfile=/hooks/archiso
|
||||
|
||||
if [ -e /hooks/miso ]; then
|
||||
vthookfile=/hooks/miso
|
||||
$SED "/^\"\$mount_handler\"/i\ $BUSYBOX_PATH/sh $VTOY_PATH/hook/arch/ventoy-disk.sh \"\$misodevice\"" -i /init
|
||||
elif [ -e /hooks/artix ]; then
|
||||
vthookfile=/hooks/artix
|
||||
$SED "/^\"\$mount_handler\"/i\ $BUSYBOX_PATH/sh $VTOY_PATH/hook/arch/ventoy-disk.sh \"\$artixdevice\"" -i /init
|
||||
else
|
||||
$SED "/^\"\$mount_handler\"/i\ $BUSYBOX_PATH/sh $VTOY_PATH/hook/arch/ventoy-disk.sh \"\$archisodevice\"" -i /init
|
||||
fi
|
||||
|
||||
if [ -f $vthookfile ]; then
|
||||
$SED '/while ! poll_device "${dev}"/a\ if /ventoy/busybox/sh /ventoy/hook/arch/ventoy-timeout.sh ${dev}; then break; fi' -i $vthookfile
|
||||
fi
|
||||
|
||||
elif $GREP -q '^KEEP_SEARCHING' /init; then
|
||||
echo 'KEEP_SEARCHING found ...' >> $VTLOG
|
||||
$SED "/^KEEP_SEARCHING/i\ $BUSYBOX_PATH/sh $VTOY_PATH/hook/arch/ovios-disk.sh " -i /init
|
||||
|
||||
$BUSYBOX_PATH/mkdir -p /dev
|
||||
$BUSYBOX_PATH/mkdir -p /sys
|
||||
$BUSYBOX_PATH/mount -t sysfs sys /sys
|
||||
|
||||
else
|
||||
# some archlinux initramfs doesn't contain device-mapper udev rules file
|
||||
ARCH_UDEV_DIR=$(ventoy_get_udev_conf_dir)
|
||||
|
51
IMG/cpio/ventoy/hook/aryalinux/disk_hook.sh
Normal file
@@ -0,0 +1,51 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. /ventoy/hook/ventoy-hook-lib.sh
|
||||
|
||||
VTPATH_OLD=$PATH; PATH=$BUSYBOX_PATH:$VTOY_PATH/tool:$PATH
|
||||
|
||||
mkdir /sys
|
||||
mount -t sysfs sys /sys
|
||||
|
||||
wait_for_usb_disk_ready
|
||||
|
||||
vtdiskname=$(get_ventoy_disk_name)
|
||||
if [ "$vtdiskname" = "unknown" ]; then
|
||||
vtlog "ventoy disk not found"
|
||||
PATH=$VTPATH_OLD
|
||||
exit 0
|
||||
fi
|
||||
|
||||
ventoy_udev_disk_common_hook "${vtdiskname#/dev/}2" "noreplace"
|
||||
|
||||
blkdev_num=$($VTOY_PATH/tool/dmsetup ls | grep ventoy | sed 's/.*(\([0-9][0-9]*\),.*\([0-9][0-9]*\).*/\1:\2/')
|
||||
blkdev_num_mknod=$($VTOY_PATH/tool/dmsetup ls | grep ventoy | sed 's/.*(\([0-9][0-9]*\),.*\([0-9][0-9]*\).*/\1 \2/')
|
||||
vtDM=$(ventoy_find_dm_id ${blkdev_num})
|
||||
|
||||
vtlog "blkdev_num=$blkdev_num blkdev_num_mknod=$blkdev_num_mknod vtDM=$vtDM"
|
||||
|
||||
if [ -b /dev/$vtDM ]; then
|
||||
vtlog "dev already exist ..."
|
||||
else
|
||||
vtlog "mknode dev ..."
|
||||
mknod -m 660 /dev/$vtDM b $blkdev_num_mknod
|
||||
fi
|
||||
|
||||
PATH=$VTPATH_OLD
|
26
IMG/cpio/ventoy/hook/aryalinux/ventoy-hook.sh
Normal file
@@ -0,0 +1,26 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. $VTOY_PATH/hook/ventoy-os-lib.sh
|
||||
|
||||
$BUSYBOX_PATH/mkdir /dev
|
||||
$BUSYBOX_PATH/mknod -m 660 /dev/console b 5 1
|
||||
|
||||
$SED "/for device in/i $BUSYBOX_PATH/sh $VTOY_PATH/hook/aryalinux/disk_hook.sh" -i /init
|
||||
#$SED "/for device in/i exec $BUSYBOX_PATH/sh" -i /init
|
25
IMG/cpio/ventoy/hook/blackPanther/ventoy-hook.sh
Normal file
@@ -0,0 +1,25 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. $VTOY_PATH/hook/ventoy-os-lib.sh
|
||||
|
||||
ventoy_set_inotify_script blackPanther/ventoy-inotifyd-hook.sh
|
||||
$BUSYBOX_PATH/cp -a $VTOY_PATH/hook/blackPanther/ventoy-inotifyd-start.sh /lib/dracut/hooks/pre-udev/00-ventoy-inotifyd-start.sh
|
||||
|
||||
$SED "s#printf\(.*\)\$CMDLINE#printf\1 root=/dev/dm-0 \$CMDLINE root=/dev/dm-0#" -i /lib/dracut-lib.sh
|
46
IMG/cpio/ventoy/hook/blackPanther/ventoy-inotifyd-hook.sh
Normal file
@@ -0,0 +1,46 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. /ventoy/hook/ventoy-hook-lib.sh
|
||||
|
||||
if is_ventoy_hook_finished; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
VTPATH_OLD=$PATH; PATH=$BUSYBOX_PATH:$VTOY_PATH/tool:$PATH
|
||||
|
||||
if is_inotify_ventoy_part $3; then
|
||||
|
||||
vtlog "##### INOTIFYD: $2/$3 is created (YES) ..."
|
||||
|
||||
vtlog "find ventoy partition ..."
|
||||
$BUSYBOX_PATH/sh $VTOY_PATH/hook/default/udev_disk_hook.sh $3 noreplace
|
||||
|
||||
blkdev_num_dev=$($VTOY_PATH/tool/dmsetup ls | grep ventoy | sed 's/.*(\([0-9][0-9]*\),.*\([0-9][0-9]*\).*/\1 \2/')
|
||||
if ! [ -e /dev/dm-0 ]; then
|
||||
mknod -m 660 /dev/dm-0 b $blkdev_num_dev
|
||||
fi
|
||||
blackPanther-root /dev/dm-0
|
||||
|
||||
set_ventoy_hook_finish
|
||||
else
|
||||
vtlog "##### INOTIFYD: $2/$3 is created (NO) ..."
|
||||
fi
|
||||
|
||||
PATH=$VTPATH_OLD
|
32
IMG/cpio/ventoy/hook/blackPanther/ventoy-inotifyd-start.sh
Normal file
@@ -0,0 +1,32 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. /ventoy/hook/ventoy-hook-lib.sh
|
||||
|
||||
vtHook=$($CAT $VTOY_PATH/inotifyd-hook-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
|
||||
|
47
IMG/cpio/ventoy/hook/cdlinux/disk-hook.sh
Normal file
@@ -0,0 +1,47 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. /ventoy/hook/ventoy-hook-lib.sh
|
||||
|
||||
if is_ventoy_hook_finished; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
vtlog "####### $0 $* ########"
|
||||
|
||||
VTPATH_OLD=$PATH; PATH=$BUSYBOX_PATH:$VTOY_PATH/tool:$PATH
|
||||
|
||||
wait_for_usb_disk_ready
|
||||
|
||||
vtdiskname=$(get_ventoy_disk_name)
|
||||
if [ "$vtdiskname" = "unknown" ]; then
|
||||
vtlog "ventoy disk not found"
|
||||
PATH=$VTPATH_OLD
|
||||
exit 0
|
||||
fi
|
||||
|
||||
ventoy_udev_disk_common_hook "${vtdiskname#/dev/}2" "noreplace"
|
||||
|
||||
blkdev_num=$($VTOY_PATH/tool/dmsetup ls | grep ventoy | sed 's/.*(\([0-9][0-9]*\),.*\([0-9][0-9]*\).*/\1 \2/')
|
||||
mknod -m 0666 /dev/ventoy b $blkdev_num
|
||||
|
||||
|
||||
PATH=$VTPATH_OLD
|
||||
|
||||
set_ventoy_hook_finish
|