Compare commits

...

111 Commits

Author SHA1 Message Date
longpanda
a129996756 1.0.33 release 2021-01-21 15:40:50 +08:00
longpanda
8632e56561 add vdiskchain module 2021-01-20 10:59:21 +08:00
longpanda
8f711c9db9 Optimization for check secure boot status in list mode. (PR #703) 2021-01-18 09:38:23 +08:00
longpanda
b0cacd6686 update 2021-01-16 23:36:32 +08:00
longpanda
13b2192a59 support for 360Udisk 2021-01-16 23:30:12 +08:00
longpanda
807d313cd5 add support for austrumi64-4.3.5.iso/slacko64-7.0.iso 2021-01-15 14:09:59 +08:00
longpanda
2f45cea46e fix a bug for arm64 ubuntu-20.10-live-server-arm64.iso 2021-01-11 13:40:14 +08:00
longpanda
7cdc7386a8 Fix a bug when use workaround for Legacy BIOS access limitation with GPT partition style 2021-01-08 20:08:32 +08:00
longpanda
44bb72ca0a add missing source 2021-01-08 11:03:32 +08:00
longpanda
5e6b0800bd update edk build script for ia32 #690 2021-01-08 09:28:16 +08:00
longpanda
01c902e026 update build script 2021-01-07 20:40:30 +08:00
longpanda
a68629a931 Add support for keyboard layout
F5 ---> Keyboard Layouts
2021-01-07 20:32:38 +08:00
longpanda
c84855bbee 1.0.32 release 2021-01-06 16:00:03 +08:00
longpanda
f2ed81b004 update 2021-01-06 07:50:23 +08:00
longpanda
6434e453b2 support for latest snapshot FreeBSD 13.0 2021-01-01 22:37:22 +08:00
longpanda
041ccb7435 dragonfly 2021-01-01 19:17:56 +08:00
longpanda
bfe194c190 DragonFly BSD support 2020-12-31 21:56:58 +08:00
longpanda
fb7008f49a 1.0.31 release 2020-12-23 19:49:12 +08:00
longpanda
463d0b2004 rebuild lz4cat64 2020-12-22 22:41:31 +08:00
longpanda
4707b76bb2 Rebuild some binaries with musl-libc to avoid virus false positive (issue #660) 2020-12-22 21:21:44 +08:00
longpanda
ff0ad76d8d add support for latest blackarch distro (issue #654) 2020-12-17 16:40:53 +08:00
longpanda
c8b2cca7c2 add support for austrumi (issue #637) 2020-12-17 16:12:46 +08:00
longpanda
afbeba7cf5 fix issue #614 2020-12-17 16:11:17 +08:00
BL4CKH47H4CK3R
bb3789f6fc Set default label from ventoy to Ventoy (#656)
Windows version has default label Ventoy instead of ventoy.
Commited just for beautifications !
2020-12-17 12:33:02 +08:00
longpanda
ea8a9e83ab workaround for 2TB+ disk 2020-12-16 23:08:36 +08:00
longpanda
8b9901a6a5 add austrumi support.(issue #637) 2020-12-15 17:42:15 +08:00
longpanda
0ac83bffda support Anarchy Linux 1.3.1 issue #642 2020-12-15 16:21:41 +08:00
longpanda
40c0504dfb 1.0.30 release 2020-12-12 17:42:45 +08:00
longpanda
ebaa4d954a IA32 ARM64 support 2020-12-12 07:56:52 +08:00
longpanda
2936666a78 Code Optimize 2020-12-12 07:40:33 +08:00
longpanda
784e3ae879 add class for submenu of 'Ventoy UEFI Utilities' 2020-11-26 14:51:13 +08:00
longpanda
d8fbd79dda 1.0.29 release 2020-11-19 20:45:17 +08:00
David P
8c192a1807 grub.cfg: add support for new Parabola ISOs (#590) 2020-11-16 11:48:41 +08:00
longpanda
e8d17f9bb1 1.0.28 release 2020-11-14 12:29:01 +08:00
longpanda
2283c3e8b0 update README.md 2020-11-13 22:15:24 +08:00
longpanda
8bbd5a14a3 最近收到一些特殊的错误报告,最后证明是非标准的Ventoy环境的原因。尤其是单分区下环境下使用 Ventoy 。
虽然 Ventoy 显示了 Unofficial 的标注信息,但是用户并不会关心,仍然会认为是 Ventoy 的问题。

Ventoy 从一开始就是一个整体的设计,并没有考虑过集成在其他bootloader或分区环境中。
Ventoy 的验证和后续新功能开发也都不会考虑这种非标准的使用方式。

因此,我决定禁止 Ventoy 在非标准环境下的使用,并且不再接受放开检查的请求。

当然,这个只是Ventoy的默认行为。Ventoy仍然是100%开源的,如果你希望把Ventoy应用在自己的环境中,你可以fork一个分支,然后修改源代码实现。
2020-11-13 16:39:15 +08:00
Victor B
f7d7db6a18 Fix typo in BuildVentoyFromSource.txt (#580) 2020-11-09 15:25:19 +08:00
longpanda
147a23c9dd 1.0.27 release 2020-10-31 19:06:30 +08:00
longpanda
062c71b972 fix a bug about VTOY_DEFAULT_IMAGE in treeview mode issue #555 2020-10-31 13:38:13 +08:00
longpanda
78ab7a0759 1.0.26 release 2020-10-24 06:26:57 +08:00
longpanda
3ebd58c9df support original order in image_list plugin 2020-10-22 09:34:46 +08:00
longpanda
ce6d379564 1.0.25 release 2020-10-21 20:33:15 +08:00
longpanda
40fdfa66b9 Optimization for Linux vDisk boot in Legacy BIOS mode 2020-10-21 17:45:44 +08:00
longpanda
9ddee7394d support different themes for Legacy BIOS mode and UEFI mode 2020-10-21 17:15:31 +08:00
longpanda
c9b316a757 Fix bug for VTOY_DEFAULT_IMAGE in TreeView mode when VTOY_DEFAULT_SEARCH_ROOT was set. 2020-10-21 13:17:29 +08:00
longpanda
1ba23bcdff add image_list plugin 2020-10-21 10:23:58 +08:00
longpanda
6630ab3585 1.0.24 release 2020-10-17 15:56:54 +08:00
longpanda
c0d478c2dd 1.0.23 release 2020-10-16 20:26:24 +08:00
longpanda
0217c5a923 fix issue #521
blackarch boot failed
2020-10-15 17:50:22 +08:00
longpanda
97312d351e fix issue #516
Arch 2020.10.1 iso boot failed in UEFI mode.
2020-10-09 19:57:35 +08:00
David P
906dc4cd41 fix Parabola EFI booting (#508) 2020-10-09 09:41:04 +08:00
longpanda
82a8b59bc7 fix issue #512
show file with name .iso
2020-10-08 17:13:40 +08:00
longpanda
b53e1fb8a8 1.0.22 release 2020-09-27 22:20:37 +08:00
longpanda
84abffc424 theme 2020-09-27 17:31:02 +08:00
longpanda
bf4e014023 linux raw boot 2020-09-27 17:23:59 +08:00
longpanda
4f840ed673 Merge branch 'master' of https://github.com/ventoy/Ventoy 2020-09-26 00:05:27 +08:00
longpanda
d02f184a8d add support for linux vdisk(vhd/vdi/raw) 2020-09-26 00:04:56 +08:00
longpanda
774e38928f update VentoyWorker.sh for nvme 2020-09-18 11:49:18 +08:00
David P
0faba673a5 fix Parabola systemd-boot loader (#473) 2020-09-14 09:56:12 +08:00
longpanda
3c649b281f update README.md 2020-09-13 14:47:44 +08:00
longpanda
5f409a1208 Fix a bug with error message null src bitmap in grub_video_bitmap_create_scaled 2020-09-13 14:43:57 +08:00
longpanda
9eb334d99a 1.0.21 release 2020-09-12 22:31:21 +08:00
longpanda
260a3269b7 Merge branch 'master' of https://github.com/ventoy/Ventoy
# Conflicts:
#	INSTALL/ventoy/ventoy.cpio
2020-09-12 02:49:39 +08:00
longpanda
a287bf8907 vhd boot
live cd
fix bug
2020-09-12 02:46:44 +08:00
longpanda
48a1b80be0 update 2020-09-03 16:45:18 +08:00
longpanda
b9ef72fbe9 Fix issue #456 2020-09-03 16:43:21 +08:00
longpanda
390507fff7 Fix issue #456 2020-09-03 16:40:26 +08:00
longpanda
a29bdfbc3c LiveCD 2020-09-03 07:46:36 +08:00
longpanda
21735f92d6 Merge branch 'master' of https://github.com/ventoy/Ventoy 2020-09-02 19:29:43 +08:00
longpanda
9a8d4d0227 update 2020-09-02 19:29:19 +08:00
longpanda
6ebe77792c Update README.md 2020-08-30 21:59:09 +08:00
longpanda
d678e54956 1.0.20 release 2020-08-30 16:34:20 +08:00
longpanda
8dce0adda6 update for new release 2020-08-29 13:12:46 +08:00
Dylan M. Taylor
1bf3e73373 Add Continuous Integration to the Project using GitHub Actions (#410)
* Create GitHub Action File for CI

* Rename c-cpp.yml to ci.yml

* Update ci.yml

* Update ci.yml

* Update ci.yml

* Update ci.yml

* Update ci.yml

* Update ci.yml

* Update ci.yml

* Update ci.yml

* Update ci.yml

* Update ci.yml
2020-08-23 21:28:56 +08:00
longpanda
a9996d6761 Update README.md 2020-08-23 16:15:02 +08:00
longpanda
dafea731c8 Update README.md 2020-08-23 16:05:27 +08:00
longpanda
6d093e88e7 update languages.ini
Add hebrew language, translated by chaim-chv
2020-08-17 22:50:55 +08:00
longpanda
58a93cdb40 1.0.19 release 2020-08-14 22:16:27 +08:00
longpanda
9962775296 update 2020-08-13 20:20:23 +08:00
BL4CKH47H4CK3R
062f816020 README Beautifications (#384) 2020-08-11 22:17:34 +08:00
f0rdprefect
89b7232b76 Fix GPT option not working if disk is over 2TB (#387) 2020-08-11 10:52:49 +08:00
longpanda
1186caba41 update 2020-08-08 19:39:35 +08:00
longpanda
be50ea69aa 1. Boot menu over serial supported
2. Optimization for booting Solus
3. Optimization for booting .efi file
4. support deepin-live iso
5. support Endless OS
6. framework for booting .img file
2020-08-07 22:25:16 +08:00
longpanda
433d854aab 1.0.18 release 2020-08-01 20:42:22 +08:00
longpanda
4cb9134e5c add mod 2020-08-01 00:30:36 +08:00
longpanda
faceaf4267 update ko 2020-07-31 23:49:01 +08:00
longpanda
37edd5a349 README.md 2020-07-31 23:47:26 +08:00
longpanda
ed0f8721d7 update README.md 2020-07-31 23:36:31 +08:00
longpanda
d80a008c04 add support to freebsd 2020-07-31 23:08:27 +08:00
longpanda
036e9cc167 Merge branch 'master' of https://github.com/ventoy/Ventoy 2020-07-26 12:12:57 +08:00
longpanda
26258653b7 fix the shell bug 2020-07-26 12:12:38 +08:00
longpanda
754e754412 1.0.17 release 2020-07-25 21:59:39 +08:00
longpanda
5af01de7c2 update vtoygpt 2020-07-25 21:33:34 +08:00
longpanda
f9763a44b2 Don't delete partition when update in GPT partition style. 2020-07-24 23:24:05 +08:00
longpanda
d063dbb7f2 fix a bug about injection plugin in GPT partition style. 2020-07-24 23:02:24 +08:00
longpanda
89938e3c78 fix a bug about update with GPT partition style. 2020-07-24 23:00:19 +08:00
longpanda
85840f626b add ICON 2020-07-23 21:35:12 +08:00
longpanda
7d1507906d 1.0.16 release 2020-07-23 18:45:08 +08:00
longpanda
0f8478fbe1 update for new release 2020-07-22 23:30:13 +08:00
longpanda
a6d3ecc7a9 change ntldr --> NTLDR 2020-07-21 21:32:51 +08:00
longpanda
5817b8b7b0 update languages.ini
add Lithuanian, translated by r0manas
2020-07-21 21:25:05 +08:00
Felix Breidenstein
8493715fb4 Fix broken links in README.md (#333) 2020-07-21 21:19:47 +08:00
longpanda
3c46432d6f Add new iso support 2020-07-18 22:07:06 +08:00
longpanda
88dcceeabc update 2020-07-17 22:50:44 +08:00
A1ive
ef204263ad add XPRESS support (#317) 2020-07-17 22:29:24 +08:00
longpanda
e08e6705cf support language font in partition Configuration Dialog 2020-07-17 17:54:16 +08:00
longpanda
a8b2fdccc7 update languages.ini 2020-07-12 20:40:12 +08:00
longpanda
85348956df update languages.ini 2020-07-11 22:38:09 +08:00
longpanda
aa0a2ed067 Merge branch 'master' of https://github.com/ventoy/Ventoy 2020-07-11 11:31:35 +08:00
longpanda
49ceaa0f61 update README.md 2020-07-11 11:29:45 +08:00
longpanda
23986d742d add debug log in Ventoy2Disk.exe 2020-07-10 10:16:25 +08:00
1259 changed files with 49566 additions and 2954 deletions

24
.github/workflows/ci.yml vendored Normal file
View 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/aarch64_ash.config Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1166
BUSYBOX/aarch64_xzcat.config Normal file

File diff suppressed because it is too large Load Diff

36
BUSYBOX/build.txt Normal file
View File

@@ -0,0 +1,36 @@
======== How to build ash/hexdump/xzcat for aarch64 ========
#How to get ash.config/hexdump.cofig/xzcat.config
#ARCH=arm64 CROSS_COMPILE=aarch64-linux- make allnoconfig
#ARCH=arm64 CROSS_COMPILE=aarch64-linux- make menuconfig
#----> enable static build
#----> enable xzcat
#get aarch64_xzcat.config
tar xf busybox-1.32.0.tar.bz2
cd busybox-1.32.0
copy aarch64_xzcat.config as .config
ARCH=arm64 CROSS_COMPILE=aarch64-linux- make
rename ./busybox to xzcat
======== How to build ash/hexdump/xzcat for x86_64 ==========
#How to get ash.config/hexdump.cofig/xzcat.config
#make allnoconfig
#make menuconfig
#----> enable static build
#----> enable xzcat
#get x86_64_xzcat.config
tar xf busybox-1.32.0.tar.bz2
cd busybox-1.32.0
copy x86_64_xzcat.config as .config
modify Makefile
CC = gcc -specs "/usr/local/musl/lib/musl-gcc.specs"
MODFLAGS = -DMODULE -specs "/usr/local/musl/lib/musl-gcc.specs"
make
rename ./busybox to xzcat

25
BUSYBOX/chmod/build.sh Normal file
View File

@@ -0,0 +1,25 @@
#!/bin/sh
DSTDIR=../../IMG/cpio/ventoy/busybox
rm -f vtchmod32 vtchmod64 vtchmod64_musl vtchmodaa64
rm -f $DSTDIR/vtchmod32 $DSTDIR/vtchmod64 $DSTDIR/vtchmodaa64
/opt/diet32/bin/diet gcc -Os -m32 vtchmod.c -o vtchmod32
/opt/diet64/bin/diet gcc -Os vtchmod.c -o vtchmod64
aarch64-linux-gcc -Os -static vtchmod.c -o vtchmodaa64
aarch64-linux-strip --strip-all vtchmodaa64
gcc -specs "/usr/local/musl/lib/musl-gcc.specs" -Os -static vtchmod.c -o vtchmod64_musl
strip --strip-all vtchmod64_musl
chmod 777 vtchmod32
chmod 777 vtchmod64
chmod 777 vtchmodaa64
chmod 777 vtchmod64_musl
cp -a vtchmod32 $DSTDIR/
cp -a vtchmod64 $DSTDIR/
cp -a vtchmodaa64 $DSTDIR/
cp -a vtchmod64_musl $DSTDIR/

13
BUSYBOX/chmod/vtchmod.c Normal file
View 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

Binary file not shown.

BIN
BUSYBOX/chmod/vtchmod64 Normal file

Binary file not shown.

Binary file not shown.

BIN
BUSYBOX/chmod/vtchmodaa64 Normal file

Binary file not shown.

1181
BUSYBOX/config Normal file

File diff suppressed because it is too large Load Diff

1166
BUSYBOX/x86_64_ash.config Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1166
BUSYBOX/x86_64_xzcat.config Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -28,4 +28,33 @@ 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 =========================
1. extract device mapper source code
2. ./configure --disable-nls --disable-selinux --disable-shared --enable-static_link CC='gcc -specs /usr/local/musl/lib/musl-gcc.specs'
3. touch include/linux/limits.h include/linux/types.h
echo '#include <sys/mount.h>' > include/linux/fs.h
4. make
5. strip --strip-all dmsetup/dmsetup.static
6. get dmsetup/dmsetup.static as the dmsetup64 binary file
======================== Build for arm64 dmsetup =========================
1. extract device mapper source code
2. ./configure CC=aarch64-linux-gcc --target=arm --host=x86_64-linux-gnu --disable-nls --disable-selinux --disable-shared --enable-static_link
3. modify include/configure.h file
--- delete the line with "#define malloc rpl_malloc"
4. make
5. aarch64-linux-strip dmsetup/dmsetup.static
6. get dmsetup/dmsetup.static as the dmsetupaa64 binary file

BIN
DMSETUP/dmsetup64 Normal file

Binary file not shown.

BIN
DMSETUP/dmsetupaa64 Normal file

Binary file not shown.

View 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
@@ -27,11 +27,26 @@
2.2 Download third-part source code
https://www.fefe.de/dietlibc/dietlibc-0.34.tar.xz ===> /home/Ventoy-master/DOC/dietlibc-0.34.tar.xz
https://musl.libc.org/releases/musl-1.2.1.tar.gz ===> /home/Ventoy-master/DOC/musl-1.2.1.tar.gz
https://ftp.gnu.org/gnu/grub/grub-2.04.tar.xz ===> /home/Ventoy-master/GRUB2/grub-2.04.tar.xz
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
https://releases.linaro.org/components/toolchain/binaries/7.4-2019.02/aarch64-linux-gnu/gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu.tar.xz ===> /opt/gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu.tar.xz
https://toolchains.bootlin.com/downloads/releases/toolchains/aarch64/tarballs/aarch64--uclibc--stable-2020.08-1.tar.bz2 ===> /opt/aarch64--uclibc--stable-2020.08-1.tar.bz2
2.3 Prepare third-part tools
cd /home/Ventoy-master/DOC/
tar xf musl-1.2.1.tar.gz
cd musl-1.2.1
./configure && make install
tar xf /opt/gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu.tar.xz -C /opt
tar xf /opt/aarch64--uclibc--stable-2020.08-1.tar.bz2 -C /opt
2.4 Set PATH envrioment
export PATH=$PATH:/opt/gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu/bin:/opt/aarch64--uclibc--stable-2020.08-1/bin
better to add this line to /root/.bashrc and relogin as root
==========================================
@@ -127,15 +142,37 @@
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/x86_64_ash.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
#aarch64
./configure --disable-nls CC='aarch64-buildroot-linux-uclibc-gcc -static'
make
aarch64-buildroot-linux-uclibc-strip --strip-all lunzip
==========================================
@@ -156,7 +193,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
@@ -164,11 +201,11 @@
https://busybox.net/downloads/binaries/1.27.1-i686 busybox_XZ
SHA-256: f6cdb6293680424c29b89bde0685ca27f455166c9b302cd6082ef90681456291
5.6 INSTALL/tool/xzcat
5.6 INSTALL/tool/i386/xzcat
https://busybox.net/downloads/binaries/1.30.0-i686/ busybox_XZCAT
SHA-256: 7399db642c2beaf52a16ab5264ffc55cfd1ff5699a524f63e5d48edf84e20f44
5.7 INSTALL/tool/hexdump
5.7 INSTALL/tool/i386/hexdump
https://busybox.net/downloads/binaries/1.30.0-i686/ busybox_HEXDUMP
SHA-256: cde08b6a2cf5ad914f05203e18e3f7c2ed6060a63604e3d75536f19b55e8e0af
@@ -202,3 +239,10 @@
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
View 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

59
EDK2/build.sh Normal file
View File

@@ -0,0 +1,59 @@
#!/bin/sh
if [ -z "$1" ]; then
EDKARCH=X64
postfix=x64
elif [ "$1" = "ia32" ]; then
EDKARCH=IA32
postfix=ia32
shift
elif [ "$1" = "aa64" ]; then
EDKARCH=AARCH64
postfix=aa64
shift
fi
cd edk2-edk2-stable201911
rm -rf ./Conf/.cache
rm -f ./Conf/.AutoGenIdFile.txt
VTEFI_PATH=Build/MdeModule/RELEASE_GCC48/$EDKARCH/MdeModulePkg/Application/Ventoy/Ventoy/OUTPUT/Ventoy.efi
DST_PATH=../../INSTALL/ventoy/ventoy_${postfix}.efi
VTEFI_PATH2=Build/MdeModule/RELEASE_GCC48/$EDKARCH/MdeModulePkg/Application/VtoyUtil/VtoyUtil/OUTPUT/VtoyUtil.efi
DST_PATH2=../../INSTALL/ventoy/vtoyutil_${postfix}.efi
VTEFI_PATH3=Build/MdeModule/RELEASE_GCC48/$EDKARCH/MdeModulePkg/Application/VDiskChain/VDiskChain/OUTPUT/VDiskChain.efi
DST_PATH3=../../VDiskChain/Tool/vdiskchain_${postfix}.efi
rm -f $VTEFI_PATH
rm -f $DST_PATH
rm -f $VTEFI_PATH2
rm -f $DST_PATH2
rm -f $VTEFI_PATH3
rm -f $DST_PATH3
source ./edksetup.sh
if [ "$EDKARCH" = "AARCH64" ]; then
PATH=$PATH:/opt/gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu/bin \
GCC48_AARCH64_PREFIX=aarch64-linux-gnu- \
build -p MdeModulePkg/MdeModulePkg.dsc -a $EDKARCH -b RELEASE -t GCC48
else
build -p MdeModulePkg/MdeModulePkg.dsc -a $EDKARCH -b RELEASE -t GCC48
fi
if [ -e $VTEFI_PATH ] && [ -e $VTEFI_PATH2 ] && [ -e $VTEFI_PATH3 ]; then
echo -e '\n\n====================== SUCCESS ========================\n\n'
cp -a $VTEFI_PATH $DST_PATH
cp -a $VTEFI_PATH2 $DST_PATH2
cp -a $VTEFI_PATH3 $DST_PATH3
cd ..
else
echo -e '\n\n====================== FAILED ========================\n\n'
cd ..
exit 1
fi

View File

@@ -11,17 +11,24 @@ cd edk2-edk2-stable201911
VTEFI_PATH=Build/MdeModule/RELEASE_GCC48/X64/MdeModulePkg/Application/Ventoy/Ventoy/OUTPUT/Ventoy.efi
DST_PATH=../../INSTALL/ventoy/ventoy_x64.efi
VTEFI_PATH2=Build/MdeModule/RELEASE_GCC48/IA32/MdeModulePkg/Application/Ventoy/Ventoy/OUTPUT/Ventoy.efi
DST_PATH2=../../INSTALL/ventoy/ventoy_ia32.efi
rm -f $VTEFI_PATH
rm -f $DST_PATH
rm -f $VTEFI_PATH2
rm -f $DST_PATH2
make -j 4 -C BaseTools/
source ./edksetup.sh
build -p MdeModulePkg/MdeModulePkg.dsc -a X64 -b RELEASE -t GCC48
build -p MdeModulePkg/MdeModulePkg.dsc -a IA32 -b RELEASE -t GCC48
if [ -e $VTEFI_PATH ]; then
if [ -e $VTEFI_PATH ] && [ -e $VTEFI_PATH2 ]; then
echo -e '\n\n====================== SUCCESS ========================\n\n'
cp -a $VTEFI_PATH $DST_PATH
cp -a $VTEFI_PATH2 $DST_PATH2
cd ..
else
echo -e '\n\n====================== FAILED ========================\n\n'

View File

@@ -0,0 +1,410 @@
/******************************************************************************
* VDiskChain.c
*
* Copyright (c) 2021, longpanda <admin@ventoy.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
*/
#include <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 <Library/UefiDecompressLib.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 <VDiskChain.h>
BOOLEAN gVDiskDebugPrint = FALSE;
vdisk_block_data gVDiskBlockData;
/* Boot filename */
CONST CHAR16 *gEfiBootFileName[] =
{
L"@",
EFI_REMOVABLE_MEDIA_FILE_NAME,
#if defined (MDE_CPU_IA32)
L"\\EFI\\BOOT\\GRUBIA32.EFI",
L"\\EFI\\BOOT\\BOOTia32.EFI",
L"\\EFI\\BOOT\\bootia32.efi",
L"\\efi\\boot\\bootia32.efi",
#elif defined (MDE_CPU_X64)
L"\\EFI\\BOOT\\GRUBX64.EFI",
L"\\EFI\\BOOT\\BOOTx64.EFI",
L"\\EFI\\BOOT\\bootx64.efi",
L"\\efi\\boot\\bootx64.efi",
#elif defined (MDE_CPU_ARM)
L"\\EFI\\BOOT\\GRUBARM.EFI",
L"\\EFI\\BOOT\\BOOTarm.EFI",
L"\\EFI\\BOOT\\bootarm.efi",
L"\\efi\\boot\\bootarm.efi",
#elif defined (MDE_CPU_AARCH64)
L"\\EFI\\BOOT\\GRUBAA64.EFI",
L"\\EFI\\BOOT\\BOOTaa64.EFI",
L"\\EFI\\BOOT\\bootaa64.efi",
L"\\efi\\boot\\bootaa64.efi",
#endif
};
UINT8 *g_disk_buf_addr = NULL;
UINT64 g_disk_buf_size = 0;
VOID EFIAPI VDiskDebug(IN CONST CHAR8 *Format, ...)
{
VA_LIST Marker;
CHAR16 Buffer[512];
VA_START (Marker, Format);
UnicodeVSPrintAsciiFormat(Buffer, sizeof(Buffer), Format, Marker);
VA_END (Marker);
gST->ConOut->OutputString(gST->ConOut, Buffer);
}
VOID EFIAPI vdisk_clear_input(VOID)
{
EFI_INPUT_KEY Key;
gST->ConIn->Reset(gST->ConIn, FALSE);
while (EFI_SUCCESS == gST->ConIn->ReadKeyStroke(gST->ConIn, &Key))
{
;
}
gST->ConIn->Reset(gST->ConIn, FALSE);
}
STATIC EFI_STATUS EFIAPI vdisk_load_image
(
IN EFI_HANDLE ImageHandle,
IN EFI_DEVICE_PATH_PROTOCOL *pDevicePath,
IN CONST CHAR16 *FileName,
IN UINTN FileNameLen,
OUT EFI_HANDLE *Image
)
{
EFI_STATUS Status = EFI_SUCCESS;
CHAR16 TmpBuf[256] = {0};
FILEPATH_DEVICE_PATH *pFilePath = NULL;
EFI_DEVICE_PATH_PROTOCOL *pImgPath = NULL;
pFilePath = (FILEPATH_DEVICE_PATH *)TmpBuf;
pFilePath->Header.Type = MEDIA_DEVICE_PATH;
pFilePath->Header.SubType = MEDIA_FILEPATH_DP;
pFilePath->Header.Length[0] = FileNameLen + sizeof(EFI_DEVICE_PATH_PROTOCOL);
pFilePath->Header.Length[1] = 0;
CopyMem(pFilePath->PathName, FileName, FileNameLen);
pImgPath = AppendDevicePathNode(pDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)pFilePath);
if (!pImgPath)
{
return EFI_NOT_FOUND;
}
Status = gBS->LoadImage(FALSE, ImageHandle, pImgPath, NULL, 0, Image);
debug("Load Image File %r DP: <%s>", Status, ConvertDevicePathToText(pImgPath, FALSE, FALSE));
FreePool(pImgPath);
return Status;
}
STATIC EFI_STATUS EFIAPI vdisk_decompress_vdisk(IN EFI_LOADED_IMAGE_PROTOCOL *pImageInfo)
{
UINT32 Size;
UINT32 DestinationSize;
UINT32 ScratchSize;
UINT8 *buf;
VOID *ScratchBuf;
EFI_STATUS Status = EFI_SUCCESS;
(VOID)pImageInfo;
vdisk_get_vdisk_raw(&buf, &Size);
UefiDecompressGetInfo(buf + VDISK_MAGIC_LEN, Size - VDISK_MAGIC_LEN, &DestinationSize, &ScratchSize);
debug("vdisk: size:%u realsize:%u", Size, DestinationSize);
g_disk_buf_size = DestinationSize;
g_disk_buf_addr = AllocatePool(DestinationSize);
ScratchBuf = AllocatePool(ScratchSize);
Status = UefiDecompress(buf + VDISK_MAGIC_LEN, g_disk_buf_addr, ScratchBuf);
FreePool(ScratchBuf);
debug("Status:%r %p %u", Status, g_disk_buf_addr, (UINT32)g_disk_buf_size);
return EFI_SUCCESS;
}
STATIC EFI_STATUS vdisk_patch_vdisk_path(CHAR16 *pos)
{
UINTN i;
UINTN j;
CHAR16 *end;
CHAR8 *buf = (char *)g_disk_buf_addr;
if (*pos == L'\"')
{
pos++;
}
end = StrStr(pos, L".vtoy");
end += 5;//string length
for (i = 0; i < g_disk_buf_size; i++)
{
if (*(UINT32 *)(buf + i) == 0x59595959)
{
for (j = 0; j < 300; j++)
{
if (buf[i + j] != 'Y')
{
break;
}
}
if (j >= 300)
{
break;
}
}
}
if (i >= g_disk_buf_size)
{
debug("No need to fill vdisk path");
return 0;
}
debug("Fill vdisk path at %d", i);
while (pos != end)
{
buf[i++] = (CHAR8)(*pos++);
}
buf[i++] = '\"';
while (buf[i] == 'Y' || buf[i] == '\"')
{
buf[i] = ' ';
i++;
}
return 0;
}
STATIC EFI_STATUS EFIAPI vdisk_parse_cmdline(IN EFI_HANDLE ImageHandle)
{
CHAR16 *Pos = NULL;
CHAR16 *pCmdLine = NULL;
EFI_STATUS Status = EFI_SUCCESS;
EFI_LOADED_IMAGE_PROTOCOL *pImageInfo = NULL;
Status = gBS->HandleProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&pImageInfo);
if (EFI_ERROR(Status))
{
VDiskDebug("Failed to handle load image protocol %r\n", 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"))
{
gVDiskDebugPrint = TRUE;
}
debug("cmdline:<%s>", pCmdLine);
vdisk_debug_pause();
Pos = StrStr(pCmdLine, L"vdisk=");
if (NULL == Pos || NULL == StrStr(pCmdLine, L".vtoy"))
{
VDiskDebug("vdisk parameter not found!\n");
return EFI_NOT_FOUND;
}
vdisk_decompress_vdisk(pImageInfo);
vdisk_patch_vdisk_path(Pos + 6);
FreePool(pCmdLine);
return EFI_SUCCESS;
}
EFI_STATUS EFIAPI vdisk_boot(IN EFI_HANDLE ImageHandle)
{
UINTN t = 0;
UINTN i = 0;
UINTN j = 0;
UINTN Find = 0;
UINTN Count = 0;
EFI_HANDLE Image = NULL;
EFI_HANDLE *Handles = NULL;
EFI_STATUS Status = EFI_SUCCESS;
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *pFile = NULL;
EFI_DEVICE_PATH_PROTOCOL *pDevPath = NULL;
for (t = 0; t < 3; t++)
{
Count = 0;
Handles = NULL;
Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiSimpleFileSystemProtocolGuid,
NULL, &Count, &Handles);
if (EFI_ERROR(Status))
{
return Status;
}
debug("vdisk_boot fs count:%u", Count);
for (i = 0; i < Count; i++)
{
Status = gBS->HandleProtocol(Handles[i], &gEfiSimpleFileSystemProtocolGuid, (VOID **)&pFile);
if (EFI_ERROR(Status))
{
continue;
}
debug("FS:%u Protocol:%p OpenVolume:%p", i, pFile, pFile->OpenVolume);
Status = gBS->OpenProtocol(Handles[i], &gEfiDevicePathProtocolGuid,
(VOID **)&pDevPath,
ImageHandle,
Handles[i],
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (EFI_ERROR(Status))
{
debug("Failed to open device path protocol %r", Status);
continue;
}
debug("Handle:%p FS DP: <%s>", Handles[i], ConvertDevicePathToText(pDevPath, FALSE, FALSE));
if (CompareMem(gVDiskBlockData.Path, pDevPath, gVDiskBlockData.DevicePathCompareLen))
{
debug("Not ventoy disk file system");
continue;
}
for (j = 1; j < ARRAY_SIZE(gEfiBootFileName); j++)
{
Status = vdisk_load_image(ImageHandle, pDevPath, gEfiBootFileName[j],
StrSize(gEfiBootFileName[j]), &Image);
if (EFI_SUCCESS == Status)
{
break;
}
debug("Failed to load image %r <%s>", Status, gEfiBootFileName[j]);
}
if (j >= ARRAY_SIZE(gEfiBootFileName))
{
continue;
}
Find++;
debug("Find boot file, now try to boot .....");
vdisk_debug_pause();
if (gVDiskDebugPrint)
{
gST->ConIn->Reset(gST->ConIn, FALSE);
}
/* can't add debug print here */
//ventoy_wrapper_system();
Status = gBS->StartImage(Image, NULL, NULL);
if (EFI_ERROR(Status))
{
debug("Failed to start image %r", Status);
sleep(3);
gBS->UnloadImage(Image);
break;
}
}
FreePool(Handles);
if (Find == 0)
{
debug("Fs not found, now wait and retry...");
sleep(2);
}
}
if (Find == 0)
{
return EFI_NOT_FOUND;
}
return EFI_SUCCESS;
}
EFI_STATUS EFIAPI VDiskChainEfiMain
(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status = EFI_SUCCESS;
gST->ConOut->ClearScreen(gST->ConOut);
vdisk_clear_input();
Status = vdisk_parse_cmdline(ImageHandle);
if (EFI_ERROR(Status))
{
return Status;
}
vdisk_install_blockio(ImageHandle, g_disk_buf_size);
vdisk_debug_pause();
Status = vdisk_boot(ImageHandle);
gBS->DisconnectController(gVDiskBlockData.Handle, NULL, NULL);
gBS->UninstallMultipleProtocolInterfaces(gVDiskBlockData.Handle,
&gEfiBlockIoProtocolGuid, &gVDiskBlockData.BlockIo,
&gEfiDevicePathProtocolGuid, gVDiskBlockData.Path,
NULL);
if (EFI_NOT_FOUND == Status)
{
gST->ConOut->OutputString(gST->ConOut, L"No bootfile found for UEFI!\r\n");
gST->ConOut->OutputString(gST->ConOut, L"Maybe the image does not support " VENTOY_UEFI_DESC L"!\r\n");
sleep(30);
}
vdisk_clear_input();
gST->ConOut->ClearScreen(gST->ConOut);
return EFI_SUCCESS;
}

View File

@@ -0,0 +1,97 @@
/******************************************************************************
* VDiskChain.h
*
* Copyright (c) 2021, longpanda <admin@ventoy.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef __VENTOY_H__
#define __VENTOY_H__
#define VDISK_MAGIC_LEN 32
#define VDISK_BLOCK_DEVICE_PATH_GUID \
{ 0x6ed2134e, 0xc2ea, 0x4943, { 0x99, 0x54, 0xa7, 0x76, 0xe5, 0x9c, 0x12, 0xc3 }}
#define VDISK_BLOCK_DEVICE_PATH_NAME L"vdisk"
#if defined (MDE_CPU_IA32)
#define VENTOY_UEFI_DESC L"IA32 UEFI"
#elif defined (MDE_CPU_X64)
#define VENTOY_UEFI_DESC L"X64 UEFI"
#elif defined (MDE_CPU_EBC)
#elif defined (MDE_CPU_ARM)
#define VENTOY_UEFI_DESC L"ARM UEFI"
#elif defined (MDE_CPU_AARCH64)
#define VENTOY_UEFI_DESC L"ARM64 UEFI"
#else
#error Unknown Processor Type
#endif
typedef struct vdisk_block_data
{
EFI_HANDLE Handle;
EFI_BLOCK_IO_MEDIA Media; /* Media descriptor */
EFI_BLOCK_IO_PROTOCOL BlockIo; /* Block I/O protocol */
UINTN DevicePathCompareLen;
EFI_DEVICE_PATH_PROTOCOL *Path; /* Device path protocol */
EFI_HANDLE RawBlockIoHandle;
EFI_BLOCK_IO_PROTOCOL *pRawBlockIo;
EFI_DEVICE_PATH_PROTOCOL *pDiskDevPath;
/* ventoy disk part2 ESP */
EFI_HANDLE DiskFsHandle;
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *pDiskFs;
EFI_DEVICE_PATH_PROTOCOL *pDiskFsDevPath;
EFI_HANDLE IsoDriverImage;
}vdisk_block_data;
#define debug(expr, ...) if (gVDiskDebugPrint) VDiskDebug("[VDISK] "expr"\r\n", ##__VA_ARGS__)
#define trace(expr, ...) VDiskDebug("[VDISK] "expr"\r\n", ##__VA_ARGS__)
#define sleep(sec) gBS->Stall(1000000 * (sec))
#define vdisk_debug_pause() \
if (gVDiskDebugPrint) \
{ \
UINTN __Index = 0; \
gST->ConOut->OutputString(gST->ConOut, L"[VDISK] ###### Press Enter to continue... ######\r\n");\
gST->ConIn->Reset(gST->ConIn, FALSE); \
gBS->WaitForEvent(1, &gST->ConIn->WaitForKey, &__Index);\
}
extern BOOLEAN gVDiskDebugPrint;
VOID EFIAPI VDiskDebug(IN CONST CHAR8 *Format, ...);
EFI_STATUS EFIAPI vdisk_block_io_read
(
IN EFI_BLOCK_IO_PROTOCOL *This,
IN UINT32 MediaId,
IN EFI_LBA Lba,
IN UINTN BufferSize,
OUT VOID *Buffer
);
extern UINT8 *g_disk_buf_addr;
extern UINT64 g_disk_buf_size;
extern vdisk_block_data gVDiskBlockData;
EFI_STATUS EFIAPI vdisk_install_blockio(IN EFI_HANDLE ImageHandle, IN UINT64 ImgSize);
int vdisk_get_vdisk_raw(UINT8 **buf, UINT32 *size);
#endif

View File

@@ -0,0 +1,82 @@
#************************************************************************************
# 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 = VDiskChain
FILE_GUID = 5bce96e3-ba11-4440-833b-299cf5849193
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
ENTRY_POINT = VDiskChainEfiMain
[Sources]
VDiskChain.h
VDiskChain.c
VDiskRawData.c
VDiskChainProtocol.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
ShellPkg/ShellPkg.dec
[LibraryClasses]
UefiApplicationEntryPoint
UefiLib
DebugLib
UefiDecompressLib
[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

View File

@@ -0,0 +1,264 @@
/******************************************************************************
* VDiskChainProtocol.c
*
* Copyright (c) 2021, longpanda <admin@ventoy.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
*/
#include <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 <VDiskChain.h>
/* EFI block device vendor device path GUID */
EFI_GUID gVDiskBlockDevicePathGuid = VDISK_BLOCK_DEVICE_PATH_GUID;
EFI_STATUS EFIAPI vdisk_block_io_reset
(
IN EFI_BLOCK_IO_PROTOCOL *This,
IN BOOLEAN ExtendedVerification
)
{
(VOID)This;
(VOID)ExtendedVerification;
return EFI_SUCCESS;
}
EFI_STATUS EFIAPI vdisk_block_io_flush(IN EFI_BLOCK_IO_PROTOCOL *This)
{
(VOID)This;
return EFI_SUCCESS;
}
EFI_STATUS EFIAPI vdisk_block_io_read
(
IN EFI_BLOCK_IO_PROTOCOL *This,
IN UINT32 MediaId,
IN EFI_LBA Lba,
IN UINTN BufferSize,
OUT VOID *Buffer
)
{
(VOID)This;
(VOID)MediaId;
debug("vdisk_block_io_read %lu %lu\n", Lba, BufferSize / 512);
CopyMem(Buffer, g_disk_buf_addr + (Lba * 512), BufferSize);
return EFI_SUCCESS;
}
EFI_STATUS EFIAPI vdisk_block_io_write
(
IN EFI_BLOCK_IO_PROTOCOL *This,
IN UINT32 MediaId,
IN EFI_LBA Lba,
IN UINTN BufferSize,
IN VOID *Buffer
)
{
(VOID)This;
(VOID)MediaId;
(VOID)Buffer;
debug("vdisk_block_io_read %lu %lu\n", Lba, BufferSize / 512);
return EFI_WRITE_PROTECTED;
}
EFI_STATUS EFIAPI vdisk_fill_device_path(VOID)
{
UINTN NameLen = 0;
UINT8 TmpBuf[128] = {0};
VENDOR_DEVICE_PATH *venPath = NULL;
venPath = (VENDOR_DEVICE_PATH *)TmpBuf;
NameLen = StrSize(VDISK_BLOCK_DEVICE_PATH_NAME);
venPath->Header.Type = HARDWARE_DEVICE_PATH;
venPath->Header.SubType = HW_VENDOR_DP;
venPath->Header.Length[0] = sizeof(VENDOR_DEVICE_PATH) + NameLen;
venPath->Header.Length[1] = 0;
CopyMem(&venPath->Guid, &gVDiskBlockDevicePathGuid, sizeof(EFI_GUID));
CopyMem(venPath + 1, VDISK_BLOCK_DEVICE_PATH_NAME, NameLen);
gVDiskBlockData.Path = AppendDevicePathNode(NULL, (EFI_DEVICE_PATH_PROTOCOL *)TmpBuf);
gVDiskBlockData.DevicePathCompareLen = sizeof(VENDOR_DEVICE_PATH) + NameLen;
debug("gVDiskBlockData.Path=<%s>\n", ConvertDevicePathToText(gVDiskBlockData.Path, FALSE, FALSE));
return EFI_SUCCESS;
}
EFI_STATUS EFIAPI vdisk_connect_driver(IN EFI_HANDLE ControllerHandle, IN CONST CHAR16 *DrvName)
{
UINTN i = 0;
UINTN Count = 0;
CHAR16 *DriverName = NULL;
EFI_HANDLE *Handles = NULL;
EFI_HANDLE DrvHandles[2] = { NULL };
EFI_STATUS Status = EFI_SUCCESS;
EFI_COMPONENT_NAME_PROTOCOL *NameProtocol = NULL;
EFI_COMPONENT_NAME2_PROTOCOL *Name2Protocol = NULL;
debug("vdisk_connect_driver <%s>...", DrvName);
Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiComponentName2ProtocolGuid,
NULL, &Count, &Handles);
if (EFI_ERROR(Status))
{
return Status;
}
for (i = 0; i < Count; i++)
{
Status = gBS->HandleProtocol(Handles[i], &gEfiComponentName2ProtocolGuid, (VOID **)&Name2Protocol);
if (EFI_ERROR(Status))
{
continue;
}
Status = Name2Protocol->GetDriverName(Name2Protocol, "en", &DriverName);
if (EFI_ERROR(Status) || NULL == DriverName)
{
continue;
}
if (StrStr(DriverName, DrvName))
{
debug("Find driver name2:<%s>: <%s>", DriverName, DrvName);
DrvHandles[0] = Handles[i];
break;
}
}
if (i < Count)
{
Status = gBS->ConnectController(ControllerHandle, DrvHandles, NULL, TRUE);
debug("vdisk_connect_driver:<%s> <%r>", DrvName, Status);
goto end;
}
debug("%s NOT found, now try COMPONENT_NAME", DrvName);
Count = 0;
FreePool(Handles);
Handles = NULL;
Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiComponentNameProtocolGuid,
NULL, &Count, &Handles);
if (EFI_ERROR(Status))
{
return Status;
}
for (i = 0; i < Count; i++)
{
Status = gBS->HandleProtocol(Handles[i], &gEfiComponentNameProtocolGuid, (VOID **)&NameProtocol);
if (EFI_ERROR(Status))
{
continue;
}
Status = NameProtocol->GetDriverName(NameProtocol, "en", &DriverName);
if (EFI_ERROR(Status))
{
continue;
}
if (StrStr(DriverName, DrvName))
{
debug("Find driver name:<%s>: <%s>", DriverName, DrvName);
DrvHandles[0] = Handles[i];
break;
}
}
if (i < Count)
{
Status = gBS->ConnectController(ControllerHandle, DrvHandles, NULL, TRUE);
debug("vdisk_connect_driver:<%s> <%r>", DrvName, Status);
goto end;
}
Status = EFI_NOT_FOUND;
end:
FreePool(Handles);
return Status;
}
EFI_STATUS EFIAPI vdisk_install_blockio(IN EFI_HANDLE ImageHandle, IN UINT64 ImgSize)
{
EFI_STATUS Status = EFI_SUCCESS;
EFI_BLOCK_IO_PROTOCOL *pBlockIo = &(gVDiskBlockData.BlockIo);
vdisk_fill_device_path();
debug("install block io protocol %p", ImageHandle);
vdisk_debug_pause();
gVDiskBlockData.Media.BlockSize = 512;
gVDiskBlockData.Media.LastBlock = ImgSize / 512 - 1;
gVDiskBlockData.Media.ReadOnly = TRUE;
gVDiskBlockData.Media.MediaPresent = 1;
gVDiskBlockData.Media.LogicalBlocksPerPhysicalBlock = 1;
pBlockIo->Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3;
pBlockIo->Media = &(gVDiskBlockData.Media);
pBlockIo->Reset = vdisk_block_io_reset;
pBlockIo->ReadBlocks = vdisk_block_io_read;
pBlockIo->WriteBlocks = vdisk_block_io_write;
pBlockIo->FlushBlocks = vdisk_block_io_flush;
Status = gBS->InstallMultipleProtocolInterfaces(&gVDiskBlockData.Handle,
&gEfiBlockIoProtocolGuid, &gVDiskBlockData.BlockIo,
&gEfiDevicePathProtocolGuid, gVDiskBlockData.Path,
NULL);
debug("Install protocol %r %p", Status, gVDiskBlockData.Handle);
if (EFI_ERROR(Status))
{
return Status;
}
Status = vdisk_connect_driver(gVDiskBlockData.Handle, L"Disk I/O Driver");
debug("Connect disk IO driver %r", Status);
Status = vdisk_connect_driver(gVDiskBlockData.Handle, L"Partition Driver");
debug("Connect partition driver %r", Status);
if (EFI_ERROR(Status))
{
Status = gBS->ConnectController(gVDiskBlockData.Handle, NULL, NULL, TRUE);
debug("Connect all controller %r", Status);
}
vdisk_debug_pause();
return EFI_SUCCESS;
}

View File

@@ -37,6 +37,9 @@
#include <Ventoy.h>
BOOLEAN gDebugPrint = FALSE;
BOOLEAN gDotEfiBoot = FALSE;
BOOLEAN gLoadIsoEfi = FALSE;
BOOLEAN gIsoUdf = FALSE;
ventoy_ram_disk g_ramdisk_param;
ventoy_chain_head *g_chain;
ventoy_img_chunk *g_chunk;
@@ -48,10 +51,14 @@ ventoy_virt_chunk *g_virt_chunk;
UINT32 g_virt_chunk_num;
vtoy_block_data gBlockData;
static grub_env_get_pf grub_env_get = NULL;
static grub_env_set_pf grub_env_set = NULL;
ventoy_grub_param_file_replace *g_file_replace_list = NULL;
ventoy_efi_file_replace g_efi_file_replace;
CONST CHAR16 gIso9660EfiDriverPath[] = ISO9660_EFI_DRIVER_PATH;
CONST CHAR16 gUdfEfiDriverPath[] = UDF_EFI_DRIVER_PATH;
BOOLEAN g_fix_windows_1st_cdrom_issue = FALSE;
STATIC BOOLEAN g_hook_keyboard = FALSE;
@@ -64,10 +71,28 @@ CONST CHAR16 *gEfiBootFileName[] =
{
L"@",
EFI_REMOVABLE_MEDIA_FILE_NAME,
#if defined (MDE_CPU_IA32)
L"\\EFI\\BOOT\\GRUBIA32.EFI",
L"\\EFI\\BOOT\\BOOTia32.EFI",
L"\\EFI\\BOOT\\bootia32.efi",
L"\\efi\\boot\\bootia32.efi",
#elif defined (MDE_CPU_X64)
L"\\EFI\\BOOT\\GRUBX64.EFI",
L"\\EFI\\BOOT\\BOOTx64.EFI",
L"\\EFI\\BOOT\\bootx64.efi",
L"\\efi\\boot\\bootx64.efi",
#elif defined (MDE_CPU_ARM)
L"\\EFI\\BOOT\\GRUBARM.EFI",
L"\\EFI\\BOOT\\BOOTarm.EFI",
L"\\EFI\\BOOT\\bootarm.efi",
L"\\efi\\boot\\bootarm.efi",
#elif defined (MDE_CPU_AARCH64)
L"\\EFI\\BOOT\\GRUBAA64.EFI",
L"\\EFI\\BOOT\\BOOTaa64.EFI",
L"\\EFI\\BOOT\\bootaa64.efi",
L"\\efi\\boot\\bootaa64.efi",
#endif
};
VOID EFIAPI VtoyDebug(IN CONST CHAR8 *Format, ...)
@@ -268,12 +293,25 @@ static int ventoy_update_image_location(ventoy_os_param *param)
}
CopyMem(&location->guid, &param->guid, sizeof(ventoy_guid));
location->image_sector_size = 2048;
location->image_sector_size = gSector512Mode ? 512 : 2048;
location->disk_sector_size = g_chain->disk_sector_size;
location->region_count = g_img_chunk_num;
region = location->regions;
if (gSector512Mode)
{
for (i = 0; i < g_img_chunk_num; i++)
{
region->image_sector_count = chunk->disk_end_sector - chunk->disk_start_sector + 1;
region->image_start_sector = chunk->img_start_sector * 4;
region->disk_start_sector = chunk->disk_start_sector;
region++;
chunk++;
}
}
else
{
for (i = 0; i < g_img_chunk_num; i++)
{
region->image_sector_count = chunk->img_end_sector - chunk->img_start_sector + 1;
@@ -282,6 +320,7 @@ static int ventoy_update_image_location(ventoy_os_param *param)
region++;
chunk++;
}
}
return 0;
}
@@ -328,7 +367,7 @@ EFI_STATUS EFIAPI ventoy_save_ramdisk_param(VOID)
Status = gRT->SetVariable(L"VentoyRamDisk", &VarGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
sizeof(g_ramdisk_param), &(g_ramdisk_param));
debug("set efi variable %r", Status);
debug("set ramdisk variable %r", Status);
return Status;
}
@@ -373,6 +412,36 @@ EFI_STATUS EFIAPI ventoy_delete_variable(VOID)
return Status;
}
#if (VENTOY_DEVICE_WARN != 0)
STATIC VOID ventoy_warn_invalid_device(VOID)
{
STATIC BOOLEAN flag = FALSE;
if (flag)
{
return;
}
flag = TRUE;
gST->ConOut->ClearScreen(gST->ConOut);
gST->ConOut->OutputString(gST->ConOut, VTOY_WARNING L"\r\n");
gST->ConOut->OutputString(gST->ConOut, VTOY_WARNING L"\r\n");
gST->ConOut->OutputString(gST->ConOut, VTOY_WARNING L"\r\n\r\n\r\n");
gST->ConOut->OutputString(gST->ConOut, L"This is NOT a standard Ventoy device and is NOT supported.\r\n\r\n");
gST->ConOut->OutputString(gST->ConOut, L"You should follow the official instructions in https://www.ventoy.net\r\n");
gST->ConOut->OutputString(gST->ConOut, L"\r\n\r\nWill exit after 10 seconds ...... ");
sleep(10);
}
#else
STATIC VOID ventoy_warn_invalid_device(VOID)
{
}
#endif
STATIC EFI_STATUS EFIAPI ventoy_load_image
(
IN EFI_HANDLE ImageHandle,
@@ -415,6 +484,7 @@ STATIC EFI_STATUS EFIAPI ventoy_find_iso_disk(IN EFI_HANDLE ImageHandle)
UINTN i = 0;
UINTN Count = 0;
UINT64 DiskSize = 0;
MBR_HEAD *pMBR = NULL;
UINT8 *pBuffer = NULL;
EFI_HANDLE *Handles;
EFI_STATUS Status = EFI_SUCCESS;
@@ -458,6 +528,18 @@ STATIC EFI_STATUS EFIAPI ventoy_find_iso_disk(IN EFI_HANDLE ImageHandle)
if (CompareMem(g_chain->os_param.vtoy_disk_guid, pBuffer + 0x180, 16) == 0)
{
pMBR = (MBR_HEAD *)pBuffer;
if (pMBR->PartTbl[0].FsFlag != 0xEE)
{
if (pMBR->PartTbl[0].StartSectorId != 2048 ||
pMBR->PartTbl[1].SectorCount != 65536 ||
pMBR->PartTbl[1].StartSectorId != pMBR->PartTbl[0].StartSectorId + pMBR->PartTbl[0].SectorCount)
{
debug("Failed to check disk part table");
ventoy_warn_invalid_device();
}
}
gBlockData.RawBlockIoHandle = Handles[i];
gBlockData.pRawBlockIo = pBlockIo;
gBS->OpenProtocol(Handles[i], &gEfiDevicePathProtocolGuid,
@@ -484,12 +566,111 @@ STATIC EFI_STATUS EFIAPI ventoy_find_iso_disk(IN EFI_HANDLE ImageHandle)
}
}
STATIC EFI_STATUS EFIAPI ventoy_find_iso_disk_fs(IN EFI_HANDLE ImageHandle)
{
UINTN i = 0;
UINTN Count = 0;
EFI_HANDLE Parent = NULL;
EFI_HANDLE *Handles = NULL;
EFI_STATUS Status = EFI_SUCCESS;
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *pFile = NULL;
EFI_DEVICE_PATH_PROTOCOL *pDevPath = NULL;
Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiSimpleFileSystemProtocolGuid,
NULL, &Count, &Handles);
if (EFI_ERROR(Status))
{
return Status;
}
debug("ventoy_find_iso_disk_fs fs count:%u", Count);
for (i = 0; i < Count; i++)
{
Status = gBS->HandleProtocol(Handles[i], &gEfiSimpleFileSystemProtocolGuid, (VOID **)&pFile);
if (EFI_ERROR(Status))
{
continue;
}
Status = gBS->OpenProtocol(Handles[i], &gEfiDevicePathProtocolGuid,
(VOID **)&pDevPath,
ImageHandle,
Handles[i],
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (EFI_ERROR(Status))
{
debug("Failed to open device path protocol %r", Status);
continue;
}
debug("Handle:%p FS DP: <%s>", Handles[i], ConvertDevicePathToText(pDevPath, FALSE, FALSE));
Parent = ventoy_get_parent_handle(pDevPath);
if (Parent == gBlockData.RawBlockIoHandle)
{
debug("Find ventoy disk fs");
gBlockData.DiskFsHandle = Handles[i];
gBlockData.pDiskFs = pFile;
gBlockData.pDiskFsDevPath = pDevPath;
break;
}
}
FreePool(Handles);
return EFI_SUCCESS;
}
STATIC EFI_STATUS EFIAPI ventoy_load_isoefi_driver(IN EFI_HANDLE ImageHandle)
{
EFI_HANDLE Image = NULL;
EFI_STATUS Status = EFI_SUCCESS;
CHAR16 LogVar[4] = L"5";
if (gIsoUdf)
{
Status = ventoy_load_image(ImageHandle, gBlockData.pDiskFsDevPath,
gUdfEfiDriverPath,
sizeof(gUdfEfiDriverPath),
&Image);
debug("load iso UDF efi driver status:%r", Status);
}
else
{
Status = ventoy_load_image(ImageHandle, gBlockData.pDiskFsDevPath,
gIso9660EfiDriverPath,
sizeof(gIso9660EfiDriverPath),
&Image);
debug("load iso 9660 efi driver status:%r", Status);
}
if (gDebugPrint)
{
gRT->SetVariable(L"FS_LOGGING", &gShellVariableGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
sizeof(LogVar), LogVar);
}
gRT->SetVariable(L"FS_NAME_NOCASE", &gShellVariableGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
sizeof(LogVar), LogVar);
gBlockData.IsoDriverImage = Image;
Status = gBS->StartImage(Image, NULL, NULL);
debug("Start iso efi driver status:%r", Status);
return EFI_SUCCESS;
}
STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
{
UINT32 i = 0;
UINT32 old_cnt = 0;
UINTN size = 0;
UINT8 chksum = 0;
const char *pEnv = NULL;
CHAR16 *pPos = NULL;
CHAR16 *pCmdLine = NULL;
EFI_STATUS Status = EFI_SUCCESS;
@@ -513,6 +694,21 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
gDebugPrint = TRUE;
}
if (StrStr(pCmdLine, L"dotefi"))
{
gDotEfiBoot = TRUE;
}
if (StrStr(pCmdLine, L"isoefi=on"))
{
gLoadIsoEfi = TRUE;
}
if (StrStr(pCmdLine, L"iso_udf"))
{
gIsoUdf = TRUE;
}
pPos = StrStr(pCmdLine, L"FirstTry=@");
if (pPos)
{
@@ -547,7 +743,19 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
}
pGrubParam = (ventoy_grub_param *)StrHexToUintn(pPos + StrLen(L"env_param="));
grub_env_set = pGrubParam->grub_env_set;
grub_env_get = pGrubParam->grub_env_get;
pEnv = grub_env_get("VTOY_CHKDEV_RESULT_STRING");
if (!pEnv)
{
return EFI_INVALID_PARAMETER;
}
if (pEnv[0] != '0' || pEnv[1] != 0)
{
ventoy_warn_invalid_device();
return EFI_INVALID_PARAMETER;
}
g_file_replace_list = &pGrubParam->file_replace;
old_cnt = g_file_replace_list->old_file_cnt;
@@ -569,16 +777,26 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
debug("memory addr:%p size:%lu", chain, size);
g_chain = AllocatePool(size);
CopyMem(g_chain, chain, size);
if (StrStr(pCmdLine, L"sector512"))
{
gSector512Mode = TRUE;
}
if (StrStr(pCmdLine, L"memdisk"))
{
g_iso_buf_size = size;
g_iso_data_buf = (UINT8 *)chain + sizeof(ventoy_chain_head);
g_iso_buf_size = size - sizeof(ventoy_chain_head);
debug("memdisk mode iso_buf_size:%u", g_iso_buf_size);
g_chain = chain;
gMemdiskMode = TRUE;
}
else
{
debug("This is normal mode");
g_chain = AllocatePool(size);
CopyMem(g_chain, chain, size);
g_chunk = (ventoy_img_chunk *)((char *)g_chain + g_chain->img_chunk_offset);
g_img_chunk_num = g_chain->img_chunk_num;
g_override_chunk = (ventoy_override_chunk *)((char *)g_chain + g_chain->override_chunk_offset);
@@ -630,6 +848,8 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
}
}
ventoy_debug_pause();
FreePool(pCmdLine);
return EFI_SUCCESS;
}
@@ -639,6 +859,11 @@ EFI_STATUS EFIAPI ventoy_clean_env(VOID)
FreePool(g_sector_flag);
g_sector_flag_num = 0;
if (gLoadIsoEfi && gBlockData.IsoDriverImage)
{
gBS->UnloadImage(gBlockData.IsoDriverImage);
}
gBS->DisconnectController(gBlockData.Handle, NULL, NULL);
gBS->UninstallMultipleProtocolInterfaces(gBlockData.Handle,
@@ -799,6 +1024,11 @@ EFI_STATUS EFIAPI ventoy_boot(IN EFI_HANDLE ImageHandle)
if (Find == 0)
{
if (gDotEfiBoot)
{
break;
}
debug("Fs not found, now wait and retry...");
sleep(2);
}
@@ -838,24 +1068,55 @@ EFI_STATUS EFIAPI VentoyEfiMain
gST->ConOut->ClearScreen(gST->ConOut);
ventoy_clear_input();
ventoy_parse_cmdline(ImageHandle);
Status = ventoy_parse_cmdline(ImageHandle);
if (EFI_ERROR(Status))
{
return Status;
}
if (gMemdiskMode)
{
g_ramdisk_param.PhyAddr = (UINT64)(UINTN)g_chain;
g_ramdisk_param.PhyAddr = (UINT64)(UINTN)g_iso_data_buf;
g_ramdisk_param.DiskSize = (UINT64)g_iso_buf_size;
ventoy_save_ramdisk_param();
if (gLoadIsoEfi)
{
ventoy_find_iso_disk(ImageHandle);
ventoy_find_iso_disk_fs(ImageHandle);
ventoy_load_isoefi_driver(ImageHandle);
}
ventoy_install_blockio(ImageHandle, g_iso_buf_size);
ventoy_debug_pause();
Status = ventoy_boot(ImageHandle);
ventoy_delete_ramdisk_param();
if (gLoadIsoEfi && gBlockData.IsoDriverImage)
{
gBS->UnloadImage(gBlockData.IsoDriverImage);
}
gBS->DisconnectController(gBlockData.Handle, NULL, NULL);
gBS->UninstallMultipleProtocolInterfaces(gBlockData.Handle,
&gEfiBlockIoProtocolGuid, &gBlockData.BlockIo,
&gEfiDevicePathProtocolGuid, gBlockData.Path,
NULL);
}
else
{
ventoy_save_variable();
ventoy_find_iso_disk(ImageHandle);
Status = ventoy_find_iso_disk(ImageHandle);
if (!EFI_ERROR(Status))
{
if (gLoadIsoEfi)
{
ventoy_find_iso_disk_fs(ImageHandle);
ventoy_load_isoefi_driver(ImageHandle);
}
ventoy_debug_pause();
@@ -864,20 +1125,29 @@ EFI_STATUS EFIAPI VentoyEfiMain
ventoy_debug_pause();
Status = ventoy_boot(ImageHandle);
}
ventoy_clean_env();
}
if (FALSE == gDotEfiBoot)
{
if (EFI_NOT_FOUND == Status)
{
gST->ConOut->OutputString(gST->ConOut, L"No bootfile found for UEFI!\r\n");
gST->ConOut->OutputString(gST->ConOut, L"Maybe the image does not support " VENTOY_UEFI_DESC L"!\r\n");
sleep(30);
}
}
ventoy_clear_input();
gST->ConOut->ClearScreen(gST->ConOut);
if (gDotEfiBoot && (EFI_NOT_FOUND == Status))
{
grub_env_set("vtoy_dotefi_retry", "YES");
}
return EFI_SUCCESS;
}

View File

@@ -168,21 +168,33 @@ typedef struct ventoy_virt_chunk
#define VTOY_BLOCK_DEVICE_PATH_GUID \
{ 0x37b87ac6, 0xc180, 0x4583, { 0xa7, 0x05, 0x41, 0x4d, 0xa8, 0xf7, 0x7e, 0xd2 }}
#define VTOY_BLOCK_DEVICE_PATH_NAME L"ventoy"
#if defined (MDE_CPU_IA32)
#define VENTOY_UEFI_DESC L"IA32 UEFI"
#define ISO9660_EFI_DRIVER_PATH L"\\ventoy\\iso9660_ia32.efi"
#define UDF_EFI_DRIVER_PATH L"\\ventoy\\udf_ia32.efi"
#elif defined (MDE_CPU_X64)
#define VENTOY_UEFI_DESC L"X64 UEFI"
#define ISO9660_EFI_DRIVER_PATH L"\\ventoy\\iso9660_x64.efi"
#define UDF_EFI_DRIVER_PATH L"\\ventoy\\udf_x64.efi"
#elif defined (MDE_CPU_EBC)
#elif defined (MDE_CPU_ARM)
#define VENTOY_UEFI_DESC L"ARM UEFI"
#define ISO9660_EFI_DRIVER_PATH L"\\ventoy\\iso9660_arm.efi"
#define UDF_EFI_DRIVER_PATH L"\\ventoy\\udf_arm.efi"
#elif defined (MDE_CPU_AARCH64)
#define VENTOY_UEFI_DESC L"ARM64 UEFI"
#define ISO9660_EFI_DRIVER_PATH L"\\ventoy\\iso9660_aa64.efi"
#define UDF_EFI_DRIVER_PATH L"\\ventoy\\udf_aa64.efi"
#else
#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
@@ -208,6 +220,7 @@ typedef struct vtoy_block_data
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *pDiskFs;
EFI_DEVICE_PATH_PROTOCOL *pDiskFsDevPath;
EFI_HANDLE IsoDriverImage;
}vtoy_block_data;
@@ -224,6 +237,7 @@ 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, ...);
@@ -252,6 +266,7 @@ 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;
@@ -270,6 +285,32 @@ typedef struct ventoy_iso9660_override
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()
@@ -335,7 +376,9 @@ 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;

View File

@@ -36,8 +36,10 @@
#include <Protocol/SimpleFileSystem.h>
#include <Ventoy.h>
UINT8 *g_iso_data_buf = NULL;
UINTN g_iso_buf_size = 0;
BOOLEAN gMemdiskMode = FALSE;
BOOLEAN gSector512Mode = FALSE;
ventoy_sector_flag *g_sector_flag = NULL;
UINT32 g_sector_flag_num = 0;
@@ -67,6 +69,10 @@ STATIC EFI_INPUT_READ_KEY g_org_read_key = NULL;
STATIC EFI_LOCATE_HANDLE g_org_locate_handle = NULL;
STATIC UINT8 g_sector_buf[2048];
STATIC EFI_BLOCK_READ g_sector_2048_read = NULL;
STATIC EFI_BLOCK_WRITE g_sector_2048_write = NULL;
BOOLEAN ventoy_is_cdrom_dp_exist(VOID)
{
UINTN i = 0;
@@ -155,10 +161,19 @@ STATIC EFI_STATUS EFIAPI ventoy_read_iso_sector
{
MapLba = (Sector - pchunk->img_start_sector) * 4 + pchunk->disk_start_sector;
}
else
else if (g_chain->disk_sector_size == 1024)
{
MapLba = (Sector - pchunk->img_start_sector) * 2048 / g_chain->disk_sector_size + pchunk->disk_start_sector;
MapLba = (Sector - pchunk->img_start_sector) * 2 + pchunk->disk_start_sector;
}
else if (g_chain->disk_sector_size == 2048)
{
MapLba = (Sector - pchunk->img_start_sector) + pchunk->disk_start_sector;
}
else if (g_chain->disk_sector_size == 4096)
{
MapLba = ((Sector - pchunk->img_start_sector) >> 1) + pchunk->disk_start_sector;
}
secLeft = pchunk->img_end_sector + 1 - Sector;
secRead = (Count < secLeft) ? Count : secLeft;
@@ -240,6 +255,96 @@ STATIC EFI_STATUS EFIAPI ventoy_read_iso_sector
return EFI_SUCCESS;
}
STATIC EFI_STATUS EFIAPI ventoy_write_iso_sector
(
IN UINT64 Sector,
IN UINTN Count,
IN VOID *Buffer
)
{
EFI_STATUS Status = EFI_SUCCESS;
EFI_LBA MapLba = 0;
UINT32 i = 0;
UINTN secLeft = 0;
UINTN secRead = 0;
UINT64 ReadStart = 0;
UINT64 ReadEnd = 0;
UINT8 *pCurBuf = (UINT8 *)Buffer;
ventoy_img_chunk *pchunk = g_chunk;
EFI_BLOCK_IO_PROTOCOL *pRawBlockIo = gBlockData.pRawBlockIo;
debug("write iso sector %lu count %u", Sector, Count);
ReadStart = Sector * 2048;
ReadEnd = (Sector + Count) * 2048;
for (i = 0; Count > 0 && i < g_img_chunk_num; i++, pchunk++)
{
if (Sector >= pchunk->img_start_sector && Sector <= pchunk->img_end_sector)
{
if (g_chain->disk_sector_size == 512)
{
MapLba = (Sector - pchunk->img_start_sector) * 4 + pchunk->disk_start_sector;
}
else if (g_chain->disk_sector_size == 1024)
{
MapLba = (Sector - pchunk->img_start_sector) * 2 + pchunk->disk_start_sector;
}
else if (g_chain->disk_sector_size == 2048)
{
MapLba = (Sector - pchunk->img_start_sector) + pchunk->disk_start_sector;
}
else if (g_chain->disk_sector_size == 4096)
{
MapLba = ((Sector - pchunk->img_start_sector) >> 1) + pchunk->disk_start_sector;
}
secLeft = pchunk->img_end_sector + 1 - Sector;
secRead = (Count < secLeft) ? Count : secLeft;
Status = pRawBlockIo->WriteBlocks(pRawBlockIo, pRawBlockIo->Media->MediaId,
MapLba, secRead * 2048, pCurBuf);
if (EFI_ERROR(Status))
{
debug("Raw disk write block failed %r LBA:%lu Count:%u", Status, MapLba, secRead);
return Status;
}
Count -= secRead;
Sector += secRead;
pCurBuf += secRead * 2048;
}
}
return EFI_SUCCESS;
}
EFI_STATUS EFIAPI ventoy_block_io_ramdisk_write
(
IN EFI_BLOCK_IO_PROTOCOL *This,
IN UINT32 MediaId,
IN EFI_LBA Lba,
IN UINTN BufferSize,
IN VOID *Buffer
)
{
(VOID)This;
(VOID)MediaId;
(VOID)Lba;
(VOID)BufferSize;
(VOID)Buffer;
if (!gSector512Mode)
{
return EFI_WRITE_PROTECTED;
}
CopyMem(g_iso_data_buf + (Lba * 2048), Buffer, BufferSize);
return EFI_SUCCESS;
}
EFI_STATUS EFIAPI ventoy_block_io_ramdisk_read
(
IN EFI_BLOCK_IO_PROTOCOL *This,
@@ -254,7 +359,7 @@ EFI_STATUS EFIAPI ventoy_block_io_ramdisk_read
(VOID)This;
(VOID)MediaId;
CopyMem(Buffer, (char *)g_chain + (Lba * 2048), BufferSize);
CopyMem(Buffer, g_iso_data_buf + (Lba * 2048), BufferSize);
if (g_blockio_start_record_bcd && FALSE == g_blockio_bcd_read_done)
{
@@ -433,14 +538,23 @@ EFI_STATUS EFIAPI ventoy_block_io_write
IN VOID *Buffer
)
{
UINT32 secNum = 0;
UINT64 offset = 0;
(VOID)This;
(VOID)MediaId;
(VOID)Lba;
(VOID)BufferSize;
(VOID)Buffer;
if (!gSector512Mode)
{
return EFI_WRITE_PROTECTED;
}
secNum = BufferSize / 2048;
offset = Lba * 2048;
return ventoy_write_iso_sector(Lba, secNum, Buffer);
}
EFI_STATUS EFIAPI ventoy_block_io_flush(IN EFI_BLOCK_IO_PROTOCOL *This)
{
(VOID)This;
@@ -570,6 +684,126 @@ end:
return Status;
}
EFI_STATUS EFIAPI ventoy_block_io_read_512
(
IN EFI_BLOCK_IO_PROTOCOL *This,
IN UINT32 MediaId,
IN EFI_LBA Lba,
IN UINTN BufferSize,
OUT VOID *Buffer
)
{
EFI_LBA Mod;
UINTN ReadSize;
UINT8 *CurBuf = NULL;
EFI_STATUS Status = EFI_SUCCESS;
debug("ventoy_block_io_read_512 %lu %lu\n", Lba, BufferSize / 512);
CurBuf = (UINT8 *)Buffer;
Mod = Lba % 4;
if (Mod > 0)
{
Status |= g_sector_2048_read(This, MediaId, Lba / 4, 2048, g_sector_buf);
if (BufferSize <= (4 - Mod) * 512)
{
CopyMem(CurBuf, g_sector_buf + Mod * 512, BufferSize);
return EFI_SUCCESS;
}
else
{
ReadSize = (4 - Mod) * 512;
CopyMem(CurBuf, g_sector_buf + Mod * 512, ReadSize);
CurBuf += ReadSize;
Lba += (4 - Mod);
BufferSize -= ReadSize;
}
}
if (BufferSize >= 2048)
{
ReadSize = BufferSize / 2048 * 2048;
Status |= g_sector_2048_read(This, MediaId, Lba / 4, ReadSize, CurBuf);
CurBuf += ReadSize;
Lba += ReadSize / 512;
BufferSize -= ReadSize;
}
if (BufferSize > 0)
{
Status |= g_sector_2048_read(This, MediaId, Lba / 4, 2048, g_sector_buf);
CopyMem(CurBuf, g_sector_buf, BufferSize);
}
return Status;
}
EFI_STATUS EFIAPI ventoy_block_io_write_512
(
IN EFI_BLOCK_IO_PROTOCOL *This,
IN UINT32 MediaId,
IN EFI_LBA Lba,
IN UINTN BufferSize,
IN VOID *Buffer
)
{
EFI_LBA Mod;
UINTN ReadSize;
UINT8 *CurBuf = NULL;
EFI_STATUS Status = EFI_SUCCESS;
debug("ventoy_block_io_write_512 %lu %lu\n", Lba, BufferSize / 512);
CurBuf = (UINT8 *)Buffer;
Mod = Lba % 4;
if (Mod > 0)
{
Status |= g_sector_2048_read(This, MediaId, Lba / 4, 2048, g_sector_buf);
if (BufferSize <= (4 - Mod) * 512)
{
CopyMem(g_sector_buf + Mod * 512, CurBuf, BufferSize);
return g_sector_2048_write(This, MediaId, Lba / 4, 2048, g_sector_buf);
}
else
{
ReadSize = (4 - Mod) * 512;
CopyMem(g_sector_buf + Mod * 512, CurBuf, ReadSize);
g_sector_2048_write(This, MediaId, Lba / 4, 2048, g_sector_buf);
CurBuf += ReadSize;
Lba += (4 - Mod);
BufferSize -= ReadSize;
}
}
if (BufferSize >= 2048)
{
ReadSize = BufferSize / 2048 * 2048;
Status |= g_sector_2048_write(This, MediaId, Lba / 4, ReadSize, CurBuf);
CurBuf += ReadSize;
Lba += ReadSize / 512;
BufferSize -= ReadSize;
}
if (BufferSize > 0)
{
Status |= g_sector_2048_read(This, MediaId, Lba / 4, 2048, g_sector_buf);
CopyMem(g_sector_buf, CurBuf, BufferSize);
g_sector_2048_write(This, MediaId, Lba / 4, 2048, g_sector_buf);
}
return Status;
}
EFI_STATUS EFIAPI ventoy_install_blockio(IN EFI_HANDLE ImageHandle, IN UINT64 ImgSize)
{
EFI_STATUS Status = EFI_SUCCESS;
@@ -580,8 +814,17 @@ EFI_STATUS EFIAPI ventoy_install_blockio(IN EFI_HANDLE ImageHandle, IN UINT64 Im
debug("install block io protocol %p", ImageHandle);
ventoy_debug_pause();
if (gSector512Mode)
{
gBlockData.Media.BlockSize = 512;
gBlockData.Media.LastBlock = ImgSize / 512 - 1;
}
else
{
gBlockData.Media.BlockSize = 2048;
gBlockData.Media.LastBlock = ImgSize / 2048 - 1;
}
gBlockData.Media.ReadOnly = TRUE;
gBlockData.Media.MediaPresent = 1;
gBlockData.Media.LogicalBlocksPerPhysicalBlock = 1;
@@ -589,8 +832,20 @@ EFI_STATUS EFIAPI ventoy_install_blockio(IN EFI_HANDLE ImageHandle, IN UINT64 Im
pBlockIo->Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3;
pBlockIo->Media = &(gBlockData.Media);
pBlockIo->Reset = ventoy_block_io_reset;
if (gSector512Mode)
{
g_sector_2048_read = gMemdiskMode ? ventoy_block_io_ramdisk_read : ventoy_block_io_read;
g_sector_2048_write = gMemdiskMode ? ventoy_block_io_ramdisk_write : ventoy_block_io_write;
pBlockIo->ReadBlocks = ventoy_block_io_read_512;
pBlockIo->WriteBlocks = ventoy_block_io_write_512;
}
else
{
pBlockIo->ReadBlocks = gMemdiskMode ? ventoy_block_io_ramdisk_read : ventoy_block_io_read;
pBlockIo->WriteBlocks = ventoy_block_io_write;
}
pBlockIo->FlushBlocks = ventoy_block_io_flush;
Status = gBS->InstallMultipleProtocolInterfaces(&gBlockData.Handle,
@@ -700,7 +955,15 @@ ventoy_wrapper_file_set_pos(EFI_FILE_HANDLE This, UINT64 Position)
{
(VOID)This;
if (Position <= g_efi_file_replace.FileSizeBytes)
{
g_efi_file_replace.CurPos = Position;
}
else
{
g_efi_file_replace.CurPos = g_efi_file_replace.FileSizeBytes;
}
return EFI_SUCCESS;
}
@@ -815,6 +1078,8 @@ STATIC EFI_STATUS EFIAPI ventoy_wrapper_file_open
CHAR8 TmpName[256];
ventoy_virt_chunk *virt = NULL;
debug("## ventoy_wrapper_file_open <%s> ", Name);
Status = g_original_fopen(This, New, Name, Mode, Attributes);
if (EFI_ERROR(Status))
{
@@ -850,6 +1115,11 @@ STATIC EFI_STATUS EFIAPI ventoy_wrapper_file_open
return Status;
}
}
if (StrCmp(Name, L"\\EFI\\BOOT") == 0)
{
(*New)->Open = ventoy_wrapper_file_open;
}
}
return Status;

View File

@@ -79,6 +79,14 @@ STATIC EFI_STATUS ParseCmdline(IN EFI_HANDLE ImageHandle)
SetMem(pCmdLine, pImageInfo->LoadOptionsSize + 4, 0);
CopyMem(pCmdLine, pImageInfo->LoadOptions, pImageInfo->LoadOptionsSize);
if (StrStr(pCmdLine, L"vtoyefitest"))
{
gST->ConOut->OutputString(gST->ConOut, L"\r\n##########################");
gST->ConOut->OutputString(gST->ConOut, L"\r\n######### VTOY #########");
gST->ConOut->OutputString(gST->ConOut, L"\r\n##########################");
return EFI_SUCCESS;
}
if (StrStr(pCmdLine, L"debug"))
{
gVtoyDebugPrint = TRUE;
@@ -102,6 +110,7 @@ STATIC EFI_STATUS ParseCmdline(IN EFI_HANDLE ImageHandle)
gCurFeature = pPos + StrLen(L"feature=");
gCmdLine = pCmdLine;
return EFI_SUCCESS;
}
@@ -116,7 +125,7 @@ EFI_STATUS EFIAPI VtoyUtilEfiMain
ParseCmdline(ImageHandle);
for (i = 0; i < ARRAY_SIZE(gFeatureList); i++)
for (i = 0; gCurFeature && i < ARRAY_SIZE(gFeatureList); i++)
{
Len = StrLen(gFeatureList[i].Cmd);
if (StrnCmp(gFeatureList[i].Cmd, gCurFeature, Len) == 0)
@@ -127,8 +136,11 @@ EFI_STATUS EFIAPI VtoyUtilEfiMain
}
}
if (gCmdLine)
{
FreePool(gCmdLine);
gCmdLine = NULL;
}
return EFI_SUCCESS;
}

View File

@@ -24,6 +24,7 @@
#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, ...);
@@ -38,6 +39,7 @@ 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;

View File

@@ -205,6 +205,7 @@
[Components]
MdeModulePkg/Application/Ventoy/Ventoy.inf
MdeModulePkg/Application/VtoyUtil/VtoyUtil.inf
MdeModulePkg/Application/VDiskChain/VDiskChain.inf
MdeModulePkg/Application/HelloWorld/HelloWorld.inf
MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.inf
MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf

View File

@@ -0,0 +1 @@
1

13
EfiISO/mkefiiso.sh Normal file
View 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/

View File

@@ -0,0 +1,32 @@
#!/bin/bash
CUR="$PWD"
if ! [ -e LIBFUSE ]; then
./buidlibfuse.sh
fi
rm -f EXFAT/shared/*
rm -rf exfat-1.3.0
unzip exfat-1.3.0.zip
sed "/printf.*VERSION/a\ if (access(\"/etc/initrd-release\", F_OK) >= 0) argv[0][0] = '@';" -i exfat-1.3.0/fuse/main.c
cd exfat-1.3.0
autoreconf --install
./configure --prefix="$CUR" CFLAGS='-O2 -D_FILE_OFFSET_BITS=64' FUSE_CFLAGS="-I$CUR/LIBFUSE/include/" FUSE_LIBS="$CUR/LIBFUSE/lib/libfuse.a -lpthread -ldl"
make
strip --strip-all fuse/mount.exfat-fuse
strip --strip-all mkfs/mkexfatfs
cp fuse/mount.exfat-fuse ../EXFAT/shared/mount.exfat-fuse
cp mkfs/mkexfatfs ../EXFAT/shared/mkexfatfs
cd ..
rm -rf exfat-1.3.0

View File

@@ -0,0 +1,29 @@
#!/bin/bash
CUR="$PWD"
rm -rf libfuse
rm -rf LIBFUSE
if [ -e mirrors-libfuse-fuse-2.9.9.zip ]; then
unzip mirrors-libfuse-fuse-2.9.9.zip
cd libfuse
else
unzip libfuse-fuse-2.9.9.zip
cd libfuse-fuse-2.9.9
fi
./makeconf.sh
./configure --prefix="$CUR/LIBFUSE"
sed '/#define *__u64/d' -i include/fuse_kernel.h
sed '/#define *__s64/d' -i include/fuse_kernel.h
sed 's/__u64/uint64_t/g' -i include/fuse_kernel.h
sed 's/__s64/int64_t/g' -i include/fuse_kernel.h
make -j 16
make install
cd ..
rm -rf libfuse

View File

@@ -11,10 +11,16 @@ else
opt=-lrt
fi
#
# use musl-c to build for x86_64
#
export C_INCLUDE_PATH=$LIBFUSE_DIR/include
rm -f $name
gcc -static -O2 -D_FILE_OFFSET_BITS=64 vtoy_fuse_iso.c -o $name $LIBFUSE_DIR/lib/libfuse.a -lpthread -ldl $opt
gcc -specs "/usr/local/musl/lib/musl-gcc.specs" -static -O2 -D_FILE_OFFSET_BITS=64 vtoy_fuse_iso.c $LIBFUSE_DIR/lib/libfuse.a -o $name
strip --strip-all $name
if [ -e $name ]; then
echo -e "\n############### SUCCESS $name ##################\n"

21
FUSEISO/build_aarch64.sh Normal file
View File

@@ -0,0 +1,21 @@
#!/bin/bash
CUR="$PWD"
LIBFUSE_DIR=$CUR/LIBFUSE
name=vtoy_fuse_iso_aa64
export C_INCLUDE_PATH=$LIBFUSE_DIR/include
rm -f $name
aarch64-buildroot-linux-uclibc-gcc -static -O2 -D_FILE_OFFSET_BITS=64 vtoy_fuse_iso.c -o $name $LIBFUSE_DIR/lib/libfuse.a
if [ -e $name ]; then
echo -e "\n############### SUCCESS $name ##################\n"
else
echo -e "\n############### FAILED $name ##################\n"
fi
aarch64-buildroot-linux-uclibc-strip --strip-all $name

View File

@@ -7,6 +7,8 @@
#
#
# use mini-native-x86_64 UCLIBC to build for x86_64
CUR="$PWD"
LIBFUSE_DIR=$CUR/LIBFUSE
@@ -31,7 +33,7 @@ fi
./makeconf.sh
./configure --prefix="$LIBFUSE_DIR"
./configure --prefix="$LIBFUSE_DIR" CFLAGS='-specs /usr/local/musl/lib/musl-gcc.specs'
make -j 16
make install
cd ..

View File

@@ -0,0 +1,46 @@
#!/bin/bash
#
#
# Package Dependency:
# gcc automake autoconf gettext gettext-devel libtool unzip
#
#
CUR="$PWD"
LIBFUSE_DIR=$CUR/LIBFUSE
rm -rf libfuse
rm -rf $LIBFUSE_DIR
# please download https://codeload.github.com/libfuse/libfuse/zip/fuse-2.9.9
if [ -e ../ExFAT/mirrors-libfuse-fuse-2.9.9.zip ]; then
rm -rf libfuse
unzip ../ExFAT/mirrors-libfuse-fuse-2.9.9.zip
cd libfuse
elif [ -e ../ExFAT/libfuse-fuse-2.9.9.zip ]; then
rm -rf libfuse-fuse-2.9.9
unzip ../ExFAT/libfuse-fuse-2.9.9.zip
cd libfuse-fuse-2.9.9
else
echo "Please download mirrors-libfuse-fuse-2.9.9.zip first"
exit 1
fi
./makeconf.sh
sed '/#define *__u64/d' -i include/fuse_kernel.h
sed '/#define *__s64/d' -i include/fuse_kernel.h
sed 's/__u64/uint64_t/g' -i include/fuse_kernel.h
sed 's/__s64/int64_t/g' -i include/fuse_kernel.h
./configure --prefix="$LIBFUSE_DIR" --host=aarch64 CC=aarch64-buildroot-linux-uclibc-gcc
make -j 16
make install
cd ..
rm -rf libfuse

View File

@@ -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;
}
}

Binary file not shown.

Binary file not shown.

BIN
FUSEISO/vtoy_fuse_iso_aa64 Normal file

Binary file not shown.

View File

@@ -809,6 +809,16 @@ module = {
common = commands/blocklist.c;
};
module = {
name = blscfg;
common = commands/blscfg.c;
common = commands/loadenv.h;
enable = powerpc_ieee1275;
enable = efi;
enable = i386_pc;
enable = emu;
};
module = {
name = boot;
common = commands/boot.c;
@@ -986,6 +996,7 @@ module = {
module = {
name = loadenv;
common = commands/loadenv.c;
common = commands/loadenv.h;
common = lib/envblk.c;
};
@@ -1578,11 +1589,20 @@ 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;
common = ventoy/miniz.c;
};
module = {
name = setkey;
common = term/setkey.c;
};
module = {

View File

@@ -479,7 +479,7 @@ LOCAL(stop):
jmp LOCAL(stop)
ventoy_uuid: .ascii "XXXXXXXXXXXXXXXX"
notification_string: .asciz "GR"
notification_string: .asciz "VT"
geometry_error_string: .asciz "Ge"
hd_probe_error_string: .asciz "HD"
read_error_string: .asciz "Rd"

File diff suppressed because it is too large Load Diff

View 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);
}

View 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);
}

View 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;
}

View 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);
}

View 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);
}

View File

@@ -735,6 +735,8 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
{
if ((dirent.flags & FLAG_TYPE) == FLAG_TYPE_DIR)
ctx.type = GRUB_FSHELP_DIR;
else if ((dirent.flags & FLAG_TYPE) == 3)
ctx.type = GRUB_FSHELP_DIR;
else
ctx.type = GRUB_FSHELP_REG;
}

View 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;
}

View 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

View File

@@ -109,6 +109,52 @@ grub_env_write_root (struct grub_env_var *var __attribute__ ((unused)),
return grub_strdup (val);
}
static int g_ventoy_hook_root = 0;
void ventoy_env_hook_root(int hook)
{
g_ventoy_hook_root = hook;
}
static char *
ventoy_env_write_root (struct grub_env_var *var __attribute__ ((unused)),
const char *val)
{
const char *pos = val;
char buf[256];
if (g_ventoy_hook_root == 0)
{
return grub_env_write_root(var, val);
}
if (pos[0] == '(')
{
pos++;
}
if (grub_strncmp(pos, "vtimghd", 7) == 0)
{
return grub_env_write_root(var, val);
}
pos = grub_strchr(val, ',');
if (!pos)
{
return grub_env_write_root(var, val);
}
if (val[0] == '(')
{
grub_snprintf(buf, sizeof(buf), "(vtimghd%s", pos);
}
else
{
grub_snprintf(buf, sizeof(buf), "vtimghd%s", pos);
}
return grub_env_write_root(var, buf);
}
static void
grub_set_prefix_and_root (void)
{
@@ -123,7 +169,7 @@ grub_set_prefix_and_root (void)
if (header->type == OBJ_TYPE_PREFIX)
prefix = (char *) header + sizeof (struct grub_module_header);
grub_register_variable_hook ("root", 0, grub_env_write_root);
grub_register_variable_hook ("root", 0, ventoy_env_write_root);
grub_machine_get_bootlocation (&fwdevice, &fwpath);

View File

@@ -0,0 +1,133 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2003,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/term.h>
#include <grub/err.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/env.h>
#include <grub/time.h>
struct grub_term_output *grub_term_outputs_disabled;
struct grub_term_input *grub_term_inputs_disabled;
struct grub_term_output *grub_term_outputs;
struct grub_term_input *grub_term_inputs;
/* Current color state. */
grub_uint8_t grub_term_normal_color = GRUB_TERM_DEFAULT_NORMAL_COLOR;
grub_uint8_t grub_term_highlight_color = GRUB_TERM_DEFAULT_HIGHLIGHT_COLOR;
void (*grub_term_poll_usb) (int wait_for_completion) = NULL;
void (*grub_net_poll_cards_idle) (void) = NULL;
/* Put a Unicode character. */
static void
grub_putcode_dumb (grub_uint32_t code,
struct grub_term_output *term)
{
struct grub_unicode_glyph c =
{
.base = code,
.variant = 0,
.attributes = 0,
.ncomb = 0,
.estimated_width = 1
};
if (code == '\t' && term->getxy)
{
int n;
n = GRUB_TERM_TAB_WIDTH - ((term->getxy (term).x)
% GRUB_TERM_TAB_WIDTH);
while (n--)
grub_putcode_dumb (' ', term);
return;
}
(term->putchar) (term, &c);
if (code == '\n')
grub_putcode_dumb ('\r', term);
}
static void
grub_xputs_dumb (const char *str)
{
for (; *str; str++)
{
grub_term_output_t term;
grub_uint32_t code = *str;
if (code > 0x7f)
code = '?';
FOR_ACTIVE_TERM_OUTPUTS(term)
grub_putcode_dumb (code, term);
}
}
void (*grub_xputs) (const char *str) = grub_xputs_dumb;
int (*grub_key_remap)(int key) = NULL;
int
grub_getkey_noblock (void)
{
grub_term_input_t term;
if (grub_term_poll_usb)
grub_term_poll_usb (0);
if (grub_net_poll_cards_idle)
grub_net_poll_cards_idle ();
FOR_ACTIVE_TERM_INPUTS(term)
{
int key = term->getkey (term);
if (grub_key_remap)
key = grub_key_remap(key);
if (key != GRUB_TERM_NO_KEY)
return key;
}
return GRUB_TERM_NO_KEY;
}
int
grub_getkey (void)
{
int ret;
grub_refresh ();
while (1)
{
ret = grub_getkey_noblock ();
if (ret != GRUB_TERM_NO_KEY)
return ret;
grub_cpu_idle ();
}
}
void
grub_refresh (void)
{
struct grub_term_output *term;
FOR_ACTIVE_TERM_OUTPUTS(term)
grub_term_refresh (term);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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;

View 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);
}

View File

@@ -803,6 +803,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
goto refresh;
case GRUB_TERM_KEY_F2:
case '2':
if (0 == g_ventoy_fn_mutex) {
cmdstr = grub_env_get("VTOY_F2_CMD");
if (cmdstr)
@@ -816,6 +817,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
}
break;
case GRUB_TERM_KEY_F3:
case '3':
if (0 == g_ventoy_fn_mutex) {
cmdstr = grub_env_get("VTOY_F3_CMD");
if (cmdstr)
@@ -827,6 +829,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
}
break;
case GRUB_TERM_KEY_F4:
case '4':
if (0 == g_ventoy_fn_mutex) {
cmdstr = grub_env_get("VTOY_F4_CMD");
if (cmdstr)
@@ -840,6 +843,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
}
break;
case GRUB_TERM_KEY_F5:
case '5':
if (0 == g_ventoy_fn_mutex) {
cmdstr = grub_env_get("VTOY_F5_CMD");
if (cmdstr)
@@ -853,15 +857,21 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
}
break;
case GRUB_TERM_KEY_F6:
case '6':
if (0 == g_ventoy_fn_mutex) {
cmdstr = grub_env_get("VTOY_F6_CMD");
if (cmdstr)
{
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)
{
@@ -871,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;
@@ -958,6 +969,9 @@ 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;
@@ -968,9 +982,15 @@ show_menu (grub_menu_t menu, int nested, int autobooted)
if (boot_entry < 0)
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)
@@ -988,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;

View File

@@ -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;

View File

@@ -0,0 +1,362 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2020 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/env.h>
#include <grub/err.h>
#include <grub/dl.h>
#include <grub/extcmd.h>
#include <grub/i18n.h>
#include <grub/term.h>
GRUB_MOD_LICENSE ("GPLv3+");
#define MAX_KEYMAP 255
struct keymap
{
int cnt;
int in[MAX_KEYMAP];
int out[MAX_KEYMAP];
};
static struct keymap setkey_keymap;
struct keysym
{
const char *name; /* the name in unshifted state */
int code; /* scan code */
};
/* The table for key symbols. (from GRUB4DOS) */
static struct keysym keysym_table[] =
{
{"escape", GRUB_TERM_ESC}, // ESC
{"exclam", 0x21}, // '!'
{"at", 0x40}, // '@'
{"numbersign", 0x23}, // '#'
{"dollar", 0x24}, // '$'
{"percent", 0x25}, // '%'
{"caret", 0x5E}, // '^'
{"ampersand", 0x26}, // '&'
{"asterisk", 0x2A}, // '*'
{"parenleft", 0x28}, // '('
{"parenright", 0x29}, // ')'
{"minus", 0x2D}, // '-'
{"underscore", 0x5F}, // '_'
{"equal", 0x3D}, // '='
{"plus", 0x2B}, // '+'
{"backspace", GRUB_TERM_BACKSPACE}, // BS
{"ctrlbackspace", GRUB_TERM_CTRL | GRUB_TERM_BACKSPACE}, // (DEL)
{"tab", GRUB_TERM_TAB}, // Tab
{"bracketleft", 0x5B}, // '['
{"braceleft", 0x7B}, // '{'
{"bracketright", 0x5D}, // ']'
{"braceright", 0x7D}, // '}'
{"enter", 0x0D}, // Enter
{"semicolon", 0x3B}, // ';'
{"colon", 0x3A}, // ':'
{"quote", 0x27}, // '\''
{"doublequote", 0x22}, // '"'
{"backquote", 0x60}, // '`'
{"tilde", 0x7E}, // '~'
{"backslash", 0x5C}, // '\\'
{"bar", 0x7C}, // '|'
{"comma", 0x2C}, // ','
{"less", 0x3C}, // '<'
{"period", 0x2E}, // '.'
{"greater", 0x3E}, // '>'
{"slash", 0x2F}, // '/'
{"question", 0x3F}, // '?'
{"space", 0x20}, // Space
{"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},
{"home", GRUB_TERM_KEY_HOME},
{"uparrow", GRUB_TERM_KEY_UP},
{"pageup", GRUB_TERM_KEY_NPAGE}, // PgUp
{"leftarrow", GRUB_TERM_KEY_LEFT},
{"center", GRUB_TERM_KEY_CENTER}, // keypad center key
{"rightarrow", GRUB_TERM_KEY_RIGHT},
{"end", GRUB_TERM_KEY_END},
{"downarrow", GRUB_TERM_KEY_DOWN},
{"pagedown", GRUB_TERM_KEY_PPAGE}, // PgDn
{"insert", GRUB_TERM_KEY_INSERT}, // Insert
{"delete", GRUB_TERM_KEY_DC}, // Delete
{"shiftF1", GRUB_TERM_SHIFT | GRUB_TERM_KEY_F1},
{"shiftF2", GRUB_TERM_SHIFT | GRUB_TERM_KEY_F2},
{"shiftF3", GRUB_TERM_SHIFT | GRUB_TERM_KEY_F3},
{"shiftF4", GRUB_TERM_SHIFT | GRUB_TERM_KEY_F4},
{"shiftF5", GRUB_TERM_SHIFT | GRUB_TERM_KEY_F5},
{"shiftF6", GRUB_TERM_SHIFT | GRUB_TERM_KEY_F6},
{"shiftF7", GRUB_TERM_SHIFT | GRUB_TERM_KEY_F7},
{"shiftF8", GRUB_TERM_SHIFT | GRUB_TERM_KEY_F8},
{"shiftF9", GRUB_TERM_SHIFT | GRUB_TERM_KEY_F9},
{"shiftF10", GRUB_TERM_SHIFT | GRUB_TERM_KEY_F10},
{"shiftF11", GRUB_TERM_SHIFT | GRUB_TERM_KEY_F11},
{"shiftF12", GRUB_TERM_SHIFT | GRUB_TERM_KEY_F12},
{"ctrlF1", GRUB_TERM_CTRL | GRUB_TERM_KEY_F1},
{"ctrlF2", GRUB_TERM_CTRL | GRUB_TERM_KEY_F2},
{"ctrlF3", GRUB_TERM_CTRL | GRUB_TERM_KEY_F3},
{"ctrlF4", GRUB_TERM_CTRL | GRUB_TERM_KEY_F4},
{"ctrlF5", GRUB_TERM_CTRL | GRUB_TERM_KEY_F5},
{"ctrlF6", GRUB_TERM_CTRL | GRUB_TERM_KEY_F6},
{"ctrlF7", GRUB_TERM_CTRL | GRUB_TERM_KEY_F7},
{"ctrlF8", GRUB_TERM_CTRL | GRUB_TERM_KEY_F8},
{"ctrlF9", GRUB_TERM_CTRL | GRUB_TERM_KEY_F9},
{"ctrlF10", GRUB_TERM_CTRL | GRUB_TERM_KEY_F10},
{"ctrlF11", GRUB_TERM_CTRL | GRUB_TERM_KEY_F11},
{"ctrlF12", GRUB_TERM_CTRL | GRUB_TERM_KEY_F12},
// A=Alt or AltGr. Provided by steve.
{"Aq", GRUB_TERM_ALT | 0x71},
{"Aw", GRUB_TERM_ALT | 0x77},
{"Ae", GRUB_TERM_ALT | 0x65},
{"Ar", GRUB_TERM_ALT | 0x72},
{"At", GRUB_TERM_ALT | 0x74},
{"Ay", GRUB_TERM_ALT | 0x79},
{"Au", GRUB_TERM_ALT | 0x75},
{"Ai", GRUB_TERM_ALT | 0x69},
{"Ao", GRUB_TERM_ALT | 0x6F},
{"Ap", GRUB_TERM_ALT | 0x70},
{"Aa", GRUB_TERM_ALT | 0x61},
{"As", GRUB_TERM_ALT | 0x73},
{"Ad", GRUB_TERM_ALT | 0x64},
{"Af", GRUB_TERM_ALT | 0x66},
{"Ag", GRUB_TERM_ALT | 0x67},
{"Ah", GRUB_TERM_ALT | 0x68},
{"Aj", GRUB_TERM_ALT | 0x6A},
{"Ak", GRUB_TERM_ALT | 0x6B},
{"Al", GRUB_TERM_ALT | 0x6C},
{"Az", GRUB_TERM_ALT | 0x7A},
{"Ax", GRUB_TERM_ALT | 0x78},
{"Ac", GRUB_TERM_ALT | 0x63},
{"Av", GRUB_TERM_ALT | 0x76},
{"Ab", GRUB_TERM_ALT | 0x62},
{"An", GRUB_TERM_ALT | 0x6E},
{"Am", GRUB_TERM_ALT | 0x6D},
{"A1", GRUB_TERM_ALT | 0x31},
{"A2", GRUB_TERM_ALT | 0x32},
{"A3", GRUB_TERM_ALT | 0x33},
{"A4", GRUB_TERM_ALT | 0x34},
{"A5", GRUB_TERM_ALT | 0x35},
{"A6", GRUB_TERM_ALT | 0x36},
{"A7", GRUB_TERM_ALT | 0x37},
{"A8", GRUB_TERM_ALT | 0x38},
{"A9", GRUB_TERM_ALT | 0x39},
{"A0", GRUB_TERM_ALT | 0x30},
//{"oem102", 0x5c},
//{"shiftoem102", 0x7c},
{"Aminus", GRUB_TERM_ALT | 0x2D},
{"Aequal", GRUB_TERM_ALT | 0x3D},
{"Abracketleft", GRUB_TERM_ALT | 0x5B},
{"Abracketright", GRUB_TERM_ALT | 0x5D},
{"Asemicolon", GRUB_TERM_ALT | 0x3B},
{"Aquote", GRUB_TERM_ALT | 0x27},
{"Abackquote", GRUB_TERM_ALT | 0x60},
{"Abackslash", GRUB_TERM_ALT | 0x5C},
{"Acomma", GRUB_TERM_ALT | 0x2C},
{"Aperiod", GRUB_TERM_ALT | 0x2E},
{"Aslash", GRUB_TERM_ALT | 0x2F},
{"Acolon", GRUB_TERM_ALT | 0x3A},
{"Aplus", GRUB_TERM_ALT | 0x2B},
{"Aless", GRUB_TERM_ALT | 0x3C},
{"Aunderscore", GRUB_TERM_ALT | 0x5F},
{"Agreater", GRUB_TERM_ALT | 0x3E},
{"Aquestion", GRUB_TERM_ALT | 0x3F},
{"Atilde", GRUB_TERM_ALT | 0x7E},
{"Abraceleft", GRUB_TERM_ALT | 0x7B},
{"Abar", GRUB_TERM_ALT | 0x7C},
{"Abraceright", GRUB_TERM_ALT | 0x7D},
{"Adoublequote", GRUB_TERM_ALT | 0x22},
};
static int grub_keymap_getkey (int key)
{
int i;
if (key == GRUB_TERM_NO_KEY)
return key;
if (setkey_keymap.cnt > MAX_KEYMAP)
setkey_keymap.cnt = MAX_KEYMAP;
for (i = 0; i < setkey_keymap.cnt; i++)
{
if (key == setkey_keymap.in[i])
{
key = setkey_keymap.out[i];
break;
}
}
return key;
}
static void
grub_keymap_reset (void)
{
grub_memset (&setkey_keymap, 0, sizeof (struct keymap));
}
static grub_err_t
grub_keymap_add (int in, int out)
{
if (in == GRUB_TERM_NO_KEY || out == GRUB_TERM_NO_KEY)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid key: %d -> %d", in, out);
if (setkey_keymap.cnt >= MAX_KEYMAP)
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
"keymap FULL %d", setkey_keymap.cnt);
setkey_keymap.in[setkey_keymap.cnt] = in;
setkey_keymap.out[setkey_keymap.cnt] = out;
setkey_keymap.cnt++;
return GRUB_ERR_NONE;
}
static void
grub_keymap_enable (void)
{
grub_key_remap = grub_keymap_getkey;
}
static void
grub_keymap_disable (void)
{
grub_key_remap = NULL;
}
static void
grub_keymap_status (void)
{
int i;
if (setkey_keymap.cnt > MAX_KEYMAP)
setkey_keymap.cnt = MAX_KEYMAP;
for (i = 0; i < setkey_keymap.cnt; i++)
{
grub_printf ("0x%x -> 0x%x\n", setkey_keymap.in[i], setkey_keymap.out[i]);
}
}
static const struct grub_arg_option options[] =
{
{"reset", 'r', 0, N_("Reset keymap."), 0, 0},
{"enable", 'e', 0, N_("Enable keymap."), 0, 0},
{"disable", 'd', 0, N_("Disable keymap."), 0, 0},
{"status", 's', 0, N_("Display keymap."), 0, 0},
{0, 0, 0, 0, 0, 0}
};
enum options
{
SETKEY_RESET,
SETKEY_ENABLE,
SETKEY_DISABLE,
SETKEY_STATUS,
};
static int
ishex (const char *str)
{
if (grub_strlen (str) < 3 || str[0] != '0')
return 0;
if (str[1] != 'x' && str[1] != 'X')
return 0;
return 1;
}
static int
parse_key (const char *str)
{
int i;
if (ishex (str))
return grub_strtol (str, NULL, 16);
if (grub_strlen (str) == 1)
return (int) str[0];
for (i = 0; i < (int) (sizeof (keysym_table) / sizeof (keysym_table[0])); i++)
{
if (grub_strcmp (str, keysym_table[i].name) == 0)
return keysym_table[i].code;
}
grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid key %s", str);
return 0;
}
static grub_err_t
grub_cmd_setkey (grub_extcmd_context_t ctxt, int argc, char **args)
{
struct grub_arg_list *state = ctxt->state;
int in, out;
if (state[SETKEY_ENABLE].set)
{
grub_keymap_enable ();
goto out;
}
if (state[SETKEY_DISABLE].set)
{
grub_keymap_disable ();
goto out;
}
if (state[SETKEY_RESET].set)
{
grub_keymap_reset ();
goto out;
}
if (state[SETKEY_STATUS].set)
{
grub_keymap_status ();
goto out;
}
if (argc != 2)
{
grub_printf
("Key names: 0-9, A-Z, a-z or escape, exclam, at, numbersign, dollar,"
"percent, caret, ampersand, asterisk, parenleft, parenright, minus,"
"underscore, equal, plus, backspace, tab, bracketleft, braceleft,"
"bracketright, braceright, enter, semicolon, colon, quote, doublequote,"
"backquote, tilde, backslash, bar, comma, less, period, greater,"
"slash, question, alt, space, delete, [ctrl|shift]F1-12."
"For Alt+ prefix with A, e.g. \'setkey at Aequal\'.");
goto out;
}
in = parse_key (args[1]);
out = parse_key (args[0]);
if (!in || !out)
goto out;
grub_keymap_add (in, out);
out:
return grub_errno;
}
static grub_extcmd_t cmd;
GRUB_MOD_INIT(setkey)
{
cmd = grub_register_extcmd ("setkey", grub_cmd_setkey, 0, N_("NEW_KEY USA_KEY"),
N_("Map default USA_KEY to NEW_KEY."), options);
}
GRUB_MOD_FINI(setkey)
{
grub_unregister_extcmd (cmd);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
#define MINIZ_HEADER_FILE_ONLY
#include "miniz.c"

File diff suppressed because it is too large Load Diff

View File

@@ -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_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,22 @@
#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 !!!!!!!!!!!!!"
#define VTOY_PLAT_I386_UEFI 0x49413332
#define VTOY_PLAT_ARM64_UEFI 0x41413634
#define VTOY_PLAT_X86_64_UEFI 0x55454649
#define VTOY_PLAT_X86_LEGACY 0x42494f53
#define VTOY_PWD_CORRUPTED(err) \
{\
grub_printf("\n\n Password corrupted, will reboot after 5 seconds.\n\n"); \
grub_refresh(); \
grub_sleep(5); \
grub_exit(); \
return (err);\
}
typedef struct ventoy_initrd_ctx
{
const char *path_prefix;
@@ -97,6 +117,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,12 +155,24 @@ 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_efi 2
#define img_type_img 3
#define img_type_vhd 4
#define img_type_vtoy 5
typedef struct img_info
{
@@ -142,6 +186,7 @@ typedef struct img_info
int id;
int type;
int plugin_list_index;
grub_uint64_t size;
int select;
int unsupport;
@@ -162,6 +207,8 @@ typedef struct img_iterator_node
int done;
int select;
int plugin_list_index;
struct img_iterator_node *parent;
struct img_iterator_node *firstchild;
@@ -206,6 +253,7 @@ extern ventoy_guid g_ventoy_guid;
extern ventoy_img_chunk_list g_img_chunk_list;
extern ventoy_img_chunk_list g_wimiso_chunk_list;
extern char *g_wimiso_path;
extern char g_arch_mode_suffix[64];
extern int g_ventoy_debug;
void ventoy_debug(const char *fmt, ...);
@@ -457,6 +505,9 @@ 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_skip_svd(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, ...);
@@ -467,6 +518,7 @@ grub_err_t ventoy_cmd_load_plugin(grub_extcmd_context_t ctxt, int argc, char **a
grub_err_t ventoy_cmd_wimdows_reset(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
@@ -590,8 +642,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];
@@ -610,6 +742,24 @@ 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;
@@ -649,6 +799,65 @@ typedef struct menu_class
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;
#define VTOY_PASSWORD_NONE 0
#define VTOY_PASSWORD_TXT 1
#define VTOY_PASSWORD_MD5 2
#define VTOY_PASSWORD_SALT_MD5 3
typedef struct vtoy_password
{
int type;
char text[128];
char salt[64];
grub_uint8_t md5[16];
}vtoy_password;
typedef struct menu_password
{
int pathlen;
char isopath[256];
vtoy_password password;
struct menu_password *next;
}menu_password;
extern int g_ventoy_menu_esc;
extern int g_ventoy_suppress_esc;
extern int g_ventoy_last_entry;
@@ -657,25 +866,79 @@ 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 grub_uint64_t g_svd_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;
extern grub_uint64_t g_ventoy_disk_size;
#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_check_password(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_fill_image_desc(grub_extcmd_context_t ctxt, int argc, char **args);
grub_err_t ventoy_cmd_unix_gzip_newko(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);
int ventoy_check_password(const vtoy_password *pwd, int retry);
int ventoy_gzip_compress(void *mem_in, int mem_in_len, void *mem_out, int mem_out_len);
grub_uint64_t ventoy_get_part1_size(ventoy_gpt_info *gpt);
#endif /* __VENTOY_DEF_H__ */

View File

@@ -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;
@@ -390,12 +390,17 @@ 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,61 @@ 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++;
}
if (g_svd_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++;
}
if (g_svd_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 +773,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 +790,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 +807,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 +822,31 @@ 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++;
}
if (g_svd_replace_offset > 0)
{
cur->img_offset = g_svd_replace_offset;
cur->override_size = 1;
cur->override_data[0] = 0xFF;
cur++;
}
return;
}
@@ -903,12 +1013,106 @@ 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, const char *file)
{
char *name;
int namelen;
int offset;
int count = 0;
char filepath[128];
grub_snprintf(filepath, sizeof(filepath), "ventoy/busybox/%s", file);
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, filepath) == 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, args[0]);
return 0;
}
grub_err_t ventoy_cmd_skip_svd(grub_extcmd_context_t ctxt, int argc, char **args)
{
int i;
grub_file_t file;
char buf[16];
(void)ctxt;
(void)argc;
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
if (!file)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Can't open file %s\n", args[0]);
}
for (i = 0; i < 10; i++)
{
buf[0] = 0;
grub_file_seek(file, (17 + i) * 2048);
grub_file_read(file, buf, 16);
if (buf[0] == 2 && grub_strncmp(buf + 1, "CD001", 5) == 0)
{
debug("Find SVD at VD %d\n", i);
g_svd_replace_offset = (17 + i) * 2048;
break;
}
}
if (i >= 10)
{
debug("SVD not found %d\n", (int)g_svd_replace_offset);
}
grub_file_close(file);
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
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;
@@ -917,14 +1121,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);
}
@@ -960,18 +1166,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
{
@@ -983,11 +1189,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);
@@ -1020,6 +1272,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);
@@ -1041,6 +1314,107 @@ 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, "64h");
}
else if (grub_strcmp(args[3], "busybox=a64") == 0)
{
debug("cpio busybox proc %s\n", args[3]);
ventoy_cpio_busybox64((cpio_newc_header *)g_ventoy_cpio_buf, "a64");
}
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);
}
@@ -1052,7 +1426,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;
@@ -1106,6 +1482,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)
{
size = sizeof(ventoy_chain_head) + img_chunk_size;
@@ -1171,20 +1550,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 */
if (virt_chunk_count > 0)
{
chain->virt_chunk_offset = chain->override_chunk_offset + override_size;
chain->virt_chunk_num = g_valid_initrd_count;
chain->virt_chunk_num = virt_chunk_count;
ventoy_linux_fill_virt_data(isosize, chain);
}
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,752 @@
/******************************************************************************
* 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;
}
static int ventoy_dragonfly_append_conf(char *buf, const char *isopath)
{
int pos = 0;
debug("ventoy_dragonfly_append_conf %s\n", isopath);
vtoy_ssprintf(buf, pos, "tmpfs_load=\"%s\"\n", "YES");
vtoy_ssprintf(buf, pos, "dm_target_linear_load=\"%s\"\n", "YES");
vtoy_ssprintf(buf, pos, "initrd.img_load=\"%s\"\n", "YES");
vtoy_ssprintf(buf, pos, "initrd.img_type=\"%s\"\n", "md_image");
vtoy_ssprintf(buf, pos, "vfs.root.mountfrom=\"%s\"\n", "ufs:md0s0");
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]);
}
else if (grub_strcmp(args[0], "DragonFly") == 0)
{
g_conf_new_len += ventoy_dragonfly_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)
{
debug("Failed to alloc memory for new ko %d\n", (int)file->size);
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_fill_image_desc(grub_extcmd_context_t ctxt, int argc, char **args)
{
int i;
grub_uint8_t *byte;
grub_uint32_t memsize;
ventoy_image_desc *desc;
grub_uint8_t flag[32] = {
0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00,
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
};
(void)ctxt;
(void)argc;
(void)args;
debug("ventoy_cmd_unix_fill_image_desc %p\n", g_mod_new_data);
if (!g_mod_new_data)
{
goto end;
}
byte = (grub_uint8_t *)g_mod_new_data;
for (i = 0; i < g_mod_new_len - 32; i += 16)
{
if (byte[i] == 0xFF && byte[i + 1] == 0xEE)
{
if (grub_memcmp(flag, byte + i, 32) == 0)
{
debug("Find position flag at %d(0x%x)\n", i, i);
break;
}
}
}
if (i >= g_mod_new_len - 32)
{
debug("Failed to find position flag %d\n", i);
goto end;
}
desc = (ventoy_image_desc *)(byte + i);
desc->disk_size = g_ventoy_disk_size;
desc->part1_size = ventoy_get_part1_size(g_ventoy_part_info);
grub_memcpy(desc->disk_uuid, g_ventoy_part_info->MBR.BootCode + 0x180, 16);
grub_memcpy(desc->disk_signature, g_ventoy_part_info->MBR.BootCode + 0x1B8, 4);
desc->img_chunk_count = g_img_chunk_list.cur_chunk;
memsize = g_img_chunk_list.cur_chunk * sizeof(ventoy_img_chunk);
debug("image chunk count:%u memsize:%u\n", desc->img_chunk_count, memsize);
if (memsize >= VTOY_SIZE_1MB * 8)
{
grub_printf("image chunk count:%u memsize:%u too big\n", desc->img_chunk_count, memsize);
goto end;
}
grub_memcpy(desc + 1, g_img_chunk_list.chunk, memsize);
end:
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
grub_err_t ventoy_cmd_unix_gzip_newko(grub_extcmd_context_t ctxt, int argc, char **args)
{
int newlen;
grub_uint8_t *buf;
(void)ctxt;
(void)argc;
(void)args;
debug("ventoy_cmd_unix_gzip_newko %p\n", g_mod_new_data);
if (!g_mod_new_data)
{
goto end;
}
buf = grub_malloc(g_mod_new_len);
if (!buf)
{
goto end;
}
newlen = ventoy_gzip_compress(g_mod_new_data, g_mod_new_len, buf, g_mod_new_len);
grub_free(g_mod_new_data);
debug("gzip org len:%d newlen:%d\n", g_mod_new_len, newlen);
g_mod_new_data = (char *)buf;
g_mod_new_len = newlen;
end:
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);
}

View File

@@ -0,0 +1,577 @@
/******************************************************************************
* 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 altboot = 0;
int offset = -1;
grub_file_t file;
grub_uint8_t data = 0;
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);
altboot = 1;
grub_env_set(args[3], "1");
break;
}
else if (gpt->PartTbl[i].LastLBA == 0)
{
break;
}
}
}
if (!altboot)
{
if (gpt->MBR.BootCode[92] == 0x22)
{
grub_file_seek(file, offset + 17908);
grub_file_read(file, &data, 1);
if (data == 0x23)
{
altboot = 1;
grub_env_set(args[3], "1");
}
}
}
}
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);
altboot = 1;
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);
}

View File

@@ -51,6 +51,7 @@ static grub_uint32_t g_suppress_wincd_override_data = 0;
grub_uint8_t g_temp_buf[512];
grub_ssize_t lzx_decompress ( const void *data, grub_size_t len, void *buf );
grub_ssize_t xca_decompress ( const void *data, grub_size_t len, void *buf );
static wim_patch *ventoy_find_wim_patch(const char *path)
{
@@ -427,7 +428,7 @@ static int ventoy_get_override_info(grub_file_t file, wim_tail *wim_data)
return 0;
}
static int ventoy_read_resource(grub_file_t fp, wim_resource_header *head, void **buffer)
static int ventoy_read_resource(grub_file_t fp, wim_header *wimhdr, wim_resource_header *head, void **buffer)
{
int decompress_len = 0;
int total_decompress = 0;
@@ -476,9 +477,16 @@ static int ventoy_read_resource(grub_file_t fp, wim_resource_header *head, void
decompress_len = (int)chunk_size;
}
else
{
if (wimhdr->flags & FLAG_HEADER_COMPRESS_XPRESS)
{
decompress_len = (int)xca_decompress(buffer_compress + cur_offset, chunk_size, cur_dst);
}
else
{
decompress_len = (int)lzx_decompress(buffer_compress + cur_offset, chunk_size, cur_dst);
}
}
//debug("chunk_size:%u decompresslen:%d\n", chunk_size, decompress_len);
@@ -498,9 +506,16 @@ static int ventoy_read_resource(grub_file_t fp, wim_resource_header *head, void
decompress_len = (int)last_chunk_size;
}
else
{
if (wimhdr->flags & FLAG_HEADER_COMPRESS_XPRESS)
{
decompress_len = (int)xca_decompress(buffer_compress + cur_offset, head->size_in_wim - cur_offset, cur_dst);
}
else
{
decompress_len = (int)lzx_decompress(buffer_compress + cur_offset, head->size_in_wim - cur_offset, cur_dst);
}
}
cur_dst += decompress_len;
total_decompress += decompress_len;
@@ -708,6 +723,24 @@ int ventoy_fill_windows_rtdata(void *buf, char *isopath)
debug("auto install script skipped or not configed %s\n", pos);
}
script = (char *)ventoy_plugin_get_injection(pos);
if (script)
{
if (ventoy_check_file_exist("%s%s", ventoy_get_env("vtoy_iso_part"), script))
{
debug("injection archive <%s> OK\n", script);
grub_snprintf(data->injection_archive, sizeof(data->injection_archive) - 1, "%s", script);
}
else
{
debug("injection archive <%s> NOT exist\n", script);
}
}
else
{
debug("injection archive not configed %s\n", pos);
}
return 0;
}
@@ -811,14 +844,14 @@ static int ventoy_wimdows_locate_wim(const char *disk, wim_patch *patch)
return 1;
}
if ((head->flags & FLAG_HEADER_COMPRESS_XPRESS) || (head->flags & FLAG_HEADER_COMPRESS_LZMS))
if (head->flags & FLAG_HEADER_COMPRESS_LZMS)
{
debug("Xpress or LZMS compress is not supported 0x%x\n", head->flags);
debug("LZMS compress is not supported 0x%x\n", head->flags);
grub_file_close(file);
return 1;
}
rc = ventoy_read_resource(file, &head->metadata, (void **)&decompress_data);
rc = ventoy_read_resource(file, head, &head->metadata, (void **)&decompress_data);
if (rc)
{
grub_printf("failed to read meta data %d\n", rc);
@@ -855,7 +888,7 @@ static int ventoy_wimdows_locate_wim(const char *disk, wim_patch *patch)
debug("find replace lookup entry_id:%ld raw_size:%u\n",
((long)patch->replace_look - (long)lookup) / sizeof(wim_lookup_entry), exe_len);
if (0 == ventoy_read_resource(file, &(patch->replace_look->resource), (void **)&(exe_data)))
if (0 == ventoy_read_resource(file, head, &(patch->replace_look->resource), (void **)&(exe_data)))
{
ventoy_cat_exe_file_data(wim_data, exe_len, exe_data);
grub_free(exe_data);
@@ -1459,7 +1492,7 @@ static grub_uint32_t ventoy_get_wim_iso_offset(const char *filepath)
grub_file_t file;
char cmdbuf[128];
grub_snprintf(cmdbuf, sizeof(cmdbuf), "loopback wimiso %s", filepath);
grub_snprintf(cmdbuf, sizeof(cmdbuf), "loopback wimiso \"%s\"", filepath);
grub_script_execute_sourcecode(cmdbuf);
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", "(wimiso)/boot/boot.wim");
@@ -1509,6 +1542,41 @@ static int ventoy_get_wim_chunklist(const char *filename, ventoy_img_chunk_list
return 0;
}
grub_err_t ventoy_cmd_wim_check_bootable(grub_extcmd_context_t ctxt, int argc, char **args)
{
grub_uint32_t boot_index;
grub_file_t file = NULL;
wim_header *wimhdr = NULL;
(void)ctxt;
(void)argc;
wimhdr = grub_zalloc(sizeof(wim_header));
if (!wimhdr)
{
return 1;
}
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
if (!file)
{
grub_free(wimhdr);
return 1;
}
grub_file_read(file, wimhdr, sizeof(wim_header));
grub_file_close(file);
boot_index = wimhdr->boot_index;
grub_free(wimhdr);
if (boot_index == 0)
{
return 1;
}
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
grub_err_t ventoy_cmd_wim_chain_data(grub_extcmd_context_t ctxt, int argc, char **args)
{
grub_uint32_t i = 0;

View 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;
}

View 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 */

View 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 */

View 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 */

View 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 */

View 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 */

View File

@@ -0,0 +1,466 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2003,2005,2007,2008,2009,2010 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_TERM_HEADER
#define GRUB_TERM_HEADER 1
#define GRUB_TERM_NO_KEY 0
/* Internal codes used by GRUB to represent terminal input. */
/* Only for keys otherwise not having shifted modification. */
#define GRUB_TERM_SHIFT 0x01000000
#define GRUB_TERM_CTRL 0x02000000
#define GRUB_TERM_ALT 0x04000000
/* Keys without associated character. */
#define GRUB_TERM_EXTENDED 0x00800000
#define GRUB_TERM_KEY_MASK 0x00ffffff
#define GRUB_TERM_KEY_LEFT (GRUB_TERM_EXTENDED | 0x4b)
#define GRUB_TERM_KEY_RIGHT (GRUB_TERM_EXTENDED | 0x4d)
#define GRUB_TERM_KEY_UP (GRUB_TERM_EXTENDED | 0x48)
#define GRUB_TERM_KEY_DOWN (GRUB_TERM_EXTENDED | 0x50)
#define GRUB_TERM_KEY_HOME (GRUB_TERM_EXTENDED | 0x47)
#define GRUB_TERM_KEY_END (GRUB_TERM_EXTENDED | 0x4f)
#define GRUB_TERM_KEY_DC (GRUB_TERM_EXTENDED | 0x53)
#define GRUB_TERM_KEY_PPAGE (GRUB_TERM_EXTENDED | 0x49)
#define GRUB_TERM_KEY_NPAGE (GRUB_TERM_EXTENDED | 0x51)
#define GRUB_TERM_KEY_F1 (GRUB_TERM_EXTENDED | 0x3b)
#define GRUB_TERM_KEY_F2 (GRUB_TERM_EXTENDED | 0x3c)
#define GRUB_TERM_KEY_F3 (GRUB_TERM_EXTENDED | 0x3d)
#define GRUB_TERM_KEY_F4 (GRUB_TERM_EXTENDED | 0x3e)
#define GRUB_TERM_KEY_F5 (GRUB_TERM_EXTENDED | 0x3f)
#define GRUB_TERM_KEY_F6 (GRUB_TERM_EXTENDED | 0x40)
#define GRUB_TERM_KEY_F7 (GRUB_TERM_EXTENDED | 0x41)
#define GRUB_TERM_KEY_F8 (GRUB_TERM_EXTENDED | 0x42)
#define GRUB_TERM_KEY_F9 (GRUB_TERM_EXTENDED | 0x43)
#define GRUB_TERM_KEY_F10 (GRUB_TERM_EXTENDED | 0x44)
#define GRUB_TERM_KEY_F11 (GRUB_TERM_EXTENDED | 0x57)
#define GRUB_TERM_KEY_F12 (GRUB_TERM_EXTENDED | 0x58)
#define GRUB_TERM_KEY_INSERT (GRUB_TERM_EXTENDED | 0x52)
#define GRUB_TERM_KEY_CENTER (GRUB_TERM_EXTENDED | 0x4c)
/* Hex value is used for ESC, since '\e' is nonstandard */
#define GRUB_TERM_ESC 0x1b
#define GRUB_TERM_TAB '\t'
#define GRUB_TERM_BACKSPACE '\b'
#define GRUB_PROGRESS_NO_UPDATE -1
#define GRUB_PROGRESS_FAST 0
#define GRUB_PROGRESS_SLOW 2
#ifndef ASM_FILE
#include <grub/err.h>
#include <grub/symbol.h>
#include <grub/types.h>
#include <grub/unicode.h>
#include <grub/list.h>
/* These are used to represent the various color states we use. */
typedef enum
{
/* The color used to display all text that does not use the
user defined colors below. */
GRUB_TERM_COLOR_STANDARD,
/* The user defined colors for normal text. */
GRUB_TERM_COLOR_NORMAL,
/* The user defined colors for highlighted text. */
GRUB_TERM_COLOR_HIGHLIGHT
}
grub_term_color_state;
/* Flags for representing the capabilities of a terminal. */
/* Some notes about the flags:
- These flags are used by higher-level functions but not terminals
themselves.
- If a terminal is dumb, you may assume that only putchar, getkey and
checkkey are called.
- Some fancy features (setcolorstate, setcolor and setcursor) can be set
to NULL. */
/* Set when input characters shouldn't be echoed back. */
#define GRUB_TERM_NO_ECHO (1 << 0)
/* Set when the editing feature should be disabled. */
#define GRUB_TERM_NO_EDIT (1 << 1)
/* Set when the terminal cannot do fancy things. */
#define GRUB_TERM_DUMB (1 << 2)
/* Which encoding does terminal expect stream to be. */
#define GRUB_TERM_CODE_TYPE_SHIFT 3
#define GRUB_TERM_CODE_TYPE_MASK (7 << GRUB_TERM_CODE_TYPE_SHIFT)
/* Only ASCII characters accepted. */
#define GRUB_TERM_CODE_TYPE_ASCII (0 << GRUB_TERM_CODE_TYPE_SHIFT)
/* Expects CP-437 characters (ASCII + pseudographics). */
#define GRUB_TERM_CODE_TYPE_CP437 (1 << GRUB_TERM_CODE_TYPE_SHIFT)
/* UTF-8 stream in logical order. Usually used for terminals
which just forward the stream to another computer. */
#define GRUB_TERM_CODE_TYPE_UTF8_LOGICAL (2 << GRUB_TERM_CODE_TYPE_SHIFT)
/* UTF-8 in visual order. Like UTF-8 logical but for buggy endpoints. */
#define GRUB_TERM_CODE_TYPE_UTF8_VISUAL (3 << GRUB_TERM_CODE_TYPE_SHIFT)
/* Glyph description in visual order. */
#define GRUB_TERM_CODE_TYPE_VISUAL_GLYPHS (4 << GRUB_TERM_CODE_TYPE_SHIFT)
/* Bitmasks for modifier keys returned by grub_getkeystatus. */
#define GRUB_TERM_STATUS_RSHIFT (1 << 0)
#define GRUB_TERM_STATUS_LSHIFT (1 << 1)
#define GRUB_TERM_STATUS_RCTRL (1 << 2)
#define GRUB_TERM_STATUS_RALT (1 << 3)
#define GRUB_TERM_STATUS_SCROLL (1 << 4)
#define GRUB_TERM_STATUS_NUM (1 << 5)
#define GRUB_TERM_STATUS_CAPS (1 << 6)
#define GRUB_TERM_STATUS_LCTRL (1 << 8)
#define GRUB_TERM_STATUS_LALT (1 << 9)
/* Menu-related geometrical constants. */
/* The number of columns/lines between messages/borders/etc. */
#define GRUB_TERM_MARGIN 1
/* The number of columns of scroll information. */
#define GRUB_TERM_SCROLL_WIDTH 1
struct grub_term_input
{
/* The next terminal. */
struct grub_term_input *next;
struct grub_term_input **prev;
/* The terminal name. */
const char *name;
/* Initialize the terminal. */
grub_err_t (*init) (struct grub_term_input *term);
/* Clean up the terminal. */
grub_err_t (*fini) (struct grub_term_input *term);
/* Get a character if any input character is available. Otherwise return -1 */
int (*getkey) (struct grub_term_input *term);
/* Get keyboard modifier status. */
int (*getkeystatus) (struct grub_term_input *term);
void *data;
};
typedef struct grub_term_input *grub_term_input_t;
/* Made in a way to fit into uint32_t and so be passed in a register. */
struct grub_term_coordinate
{
grub_uint16_t x;
grub_uint16_t y;
};
struct grub_term_output
{
/* The next terminal. */
struct grub_term_output *next;
struct grub_term_output **prev;
/* The terminal name. */
const char *name;
/* Initialize the terminal. */
grub_err_t (*init) (struct grub_term_output *term);
/* Clean up the terminal. */
grub_err_t (*fini) (struct grub_term_output *term);
/* Put a character. C is encoded in Unicode. */
void (*putchar) (struct grub_term_output *term,
const struct grub_unicode_glyph *c);
/* Get the number of columns occupied by a given character C. C is
encoded in Unicode. */
grub_size_t (*getcharwidth) (struct grub_term_output *term,
const struct grub_unicode_glyph *c);
/* Get the screen size. */
struct grub_term_coordinate (*getwh) (struct grub_term_output *term);
/* Get the cursor position. The return value is ((X << 8) | Y). */
struct grub_term_coordinate (*getxy) (struct grub_term_output *term);
/* Go to the position (X, Y). */
void (*gotoxy) (struct grub_term_output *term,
struct grub_term_coordinate pos);
/* Clear the screen. */
void (*cls) (struct grub_term_output *term);
/* Set the current color to be used */
void (*setcolorstate) (struct grub_term_output *term,
grub_term_color_state state);
/* Turn on/off the cursor. */
void (*setcursor) (struct grub_term_output *term, int on);
/* Update the screen. */
void (*refresh) (struct grub_term_output *term);
/* gfxterm only: put in fullscreen mode. */
grub_err_t (*fullscreen) (void);
/* The feature flags defined above. */
grub_uint32_t flags;
/* Progress data. */
grub_uint32_t progress_update_divisor;
grub_uint32_t progress_update_counter;
void *data;
};
typedef struct grub_term_output *grub_term_output_t;
#define GRUB_TERM_DEFAULT_NORMAL_COLOR 0x07
#define GRUB_TERM_DEFAULT_HIGHLIGHT_COLOR 0x70
#define GRUB_TERM_DEFAULT_STANDARD_COLOR 0x07
/* Current color state. */
extern grub_uint8_t EXPORT_VAR(grub_term_normal_color);
extern grub_uint8_t EXPORT_VAR(grub_term_highlight_color);
extern struct grub_term_output *EXPORT_VAR(grub_term_outputs_disabled);
extern struct grub_term_input *EXPORT_VAR(grub_term_inputs_disabled);
extern struct grub_term_output *EXPORT_VAR(grub_term_outputs);
extern struct grub_term_input *EXPORT_VAR(grub_term_inputs);
static inline void
grub_term_register_input (const char *name __attribute__ ((unused)),
grub_term_input_t term)
{
if (grub_term_inputs)
grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs_disabled),
GRUB_AS_LIST (term));
else
{
/* If this is the first terminal, enable automatically. */
if (! term->init || term->init (term) == GRUB_ERR_NONE)
grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs), GRUB_AS_LIST (term));
}
}
static inline void
grub_term_register_input_inactive (const char *name __attribute__ ((unused)),
grub_term_input_t term)
{
grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs_disabled),
GRUB_AS_LIST (term));
}
static inline void
grub_term_register_input_active (const char *name __attribute__ ((unused)),
grub_term_input_t term)
{
if (! term->init || term->init (term) == GRUB_ERR_NONE)
grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs), GRUB_AS_LIST (term));
}
static inline void
grub_term_register_output (const char *name __attribute__ ((unused)),
grub_term_output_t term)
{
if (grub_term_outputs)
grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs_disabled),
GRUB_AS_LIST (term));
else
{
/* If this is the first terminal, enable automatically. */
if (! term->init || term->init (term) == GRUB_ERR_NONE)
grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs),
GRUB_AS_LIST (term));
}
}
static inline void
grub_term_register_output_inactive (const char *name __attribute__ ((unused)),
grub_term_output_t term)
{
grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs_disabled),
GRUB_AS_LIST (term));
}
static inline void
grub_term_register_output_active (const char *name __attribute__ ((unused)),
grub_term_output_t term)
{
if (! term->init || term->init (term) == GRUB_ERR_NONE)
grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs),
GRUB_AS_LIST (term));
}
static inline void
grub_term_unregister_input (grub_term_input_t term)
{
grub_list_remove (GRUB_AS_LIST (term));
grub_list_remove (GRUB_AS_LIST (term));
}
static inline void
grub_term_unregister_output (grub_term_output_t term)
{
grub_list_remove (GRUB_AS_LIST (term));
grub_list_remove (GRUB_AS_LIST (term));
}
#define FOR_ACTIVE_TERM_INPUTS(var) FOR_LIST_ELEMENTS((var), (grub_term_inputs))
#define FOR_DISABLED_TERM_INPUTS(var) FOR_LIST_ELEMENTS((var), (grub_term_inputs_disabled))
#define FOR_ACTIVE_TERM_OUTPUTS(var) FOR_LIST_ELEMENTS((var), (grub_term_outputs))
#define FOR_DISABLED_TERM_OUTPUTS(var) FOR_LIST_ELEMENTS((var), (grub_term_outputs_disabled))
void grub_putcode (grub_uint32_t code, struct grub_term_output *term);
int EXPORT_FUNC(grub_getkey) (void);
int EXPORT_FUNC(grub_getkey_noblock) (void);
extern int (*EXPORT_VAR (grub_key_remap))(int key);
void grub_cls (void);
void EXPORT_FUNC(grub_refresh) (void);
void grub_puts_terminal (const char *str, struct grub_term_output *term);
struct grub_term_coordinate *grub_term_save_pos (void);
void grub_term_restore_pos (struct grub_term_coordinate *pos);
static inline unsigned grub_term_width (struct grub_term_output *term)
{
return term->getwh(term).x ? : 80;
}
static inline unsigned grub_term_height (struct grub_term_output *term)
{
return term->getwh(term).y ? : 24;
}
static inline struct grub_term_coordinate
grub_term_getxy (struct grub_term_output *term)
{
return term->getxy (term);
}
static inline void
grub_term_refresh (struct grub_term_output *term)
{
if (term->refresh)
term->refresh (term);
}
static inline void
grub_term_gotoxy (struct grub_term_output *term, struct grub_term_coordinate pos)
{
term->gotoxy (term, pos);
}
static inline void
grub_term_setcolorstate (struct grub_term_output *term,
grub_term_color_state state)
{
if (term->setcolorstate)
term->setcolorstate (term, state);
}
static inline void
grub_setcolorstate (grub_term_color_state state)
{
struct grub_term_output *term;
FOR_ACTIVE_TERM_OUTPUTS(term)
grub_term_setcolorstate (term, state);
}
/* Turn on/off the cursor. */
static inline void
grub_term_setcursor (struct grub_term_output *term, int on)
{
if (term->setcursor)
term->setcursor (term, on);
}
static inline void
grub_term_cls (struct grub_term_output *term)
{
if (term->cls)
(term->cls) (term);
else
{
grub_putcode ('\n', term);
grub_term_refresh (term);
}
}
#if HAVE_FONT_SOURCE
grub_size_t
grub_unicode_estimate_width (const struct grub_unicode_glyph *c);
#else
static inline grub_size_t
grub_unicode_estimate_width (const struct grub_unicode_glyph *c __attribute__ ((unused)))
{
if (grub_unicode_get_comb_type (c->base))
return 0;
return 1;
}
#endif
#define GRUB_TERM_TAB_WIDTH 8
static inline grub_size_t
grub_term_getcharwidth (struct grub_term_output *term,
const struct grub_unicode_glyph *c)
{
if (c->base == '\t')
return GRUB_TERM_TAB_WIDTH;
if (term->getcharwidth)
return term->getcharwidth (term, c);
else if (((term->flags & GRUB_TERM_CODE_TYPE_MASK)
== GRUB_TERM_CODE_TYPE_UTF8_LOGICAL)
|| ((term->flags & GRUB_TERM_CODE_TYPE_MASK)
== GRUB_TERM_CODE_TYPE_UTF8_VISUAL)
|| ((term->flags & GRUB_TERM_CODE_TYPE_MASK)
== GRUB_TERM_CODE_TYPE_VISUAL_GLYPHS))
return grub_unicode_estimate_width (c);
else
return 1;
}
struct grub_term_autoload
{
struct grub_term_autoload *next;
char *name;
char *modname;
};
extern struct grub_term_autoload *grub_term_input_autoload;
extern struct grub_term_autoload *grub_term_output_autoload;
static inline void
grub_print_spaces (struct grub_term_output *term, int number_spaces)
{
while (--number_spaces >= 0)
grub_putcode (' ', term);
}
extern void (*EXPORT_VAR (grub_term_poll_usb)) (int wait_for_completion);
#define GRUB_TERM_REPEAT_PRE_INTERVAL 400
#define GRUB_TERM_REPEAT_INTERVAL 50
#endif /* ! ASM_FILE */
#endif /* ! GRUB_TERM_HEADER */

View File

@@ -21,7 +21,7 @@
#ifndef __VENTOY_H__
#define __VENTOY_H__
#define COMPILE_ASSERT(expr) extern char __compile_assert[(expr) ? 1 : -1]
#define COMPILE_ASSERT(a, expr) extern char __compile_assert##a[(expr) ? 1 : -1]
#define VENTOY_COMPATIBLE_STR "VENTOY COMPATIBLE"
#define VENTOY_COMPATIBLE_STR_LEN 17
@@ -71,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 */
@@ -125,22 +125,35 @@ typedef struct ventoy_os_param
*/
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;
typedef struct ventoy_secure_data
{
grub_uint8_t magic1[16]; /* VENTOY_GUID */
grub_uint8_t diskuuid[16];
grub_uint8_t Checksum[16];
grub_uint8_t adminSHA256[32];
grub_uint8_t reserved[4000];
grub_uint8_t magic2[16]; /* VENTOY_GUID */
}ventoy_secure_data;
#pragma pack()
// compile assert check : sizeof(ventoy_os_param) must be 512
COMPILE_ASSERT(sizeof(ventoy_os_param) == 512);
COMPILE_ASSERT(1,sizeof(ventoy_os_param) == 512);
COMPILE_ASSERT(2,sizeof(ventoy_secure_data) == 4096);
@@ -173,6 +186,18 @@ typedef struct ventoy_chain_head
grub_uint32_t virt_chunk_num;
}ventoy_chain_head;
typedef struct ventoy_image_desc
{
grub_uint64_t disk_size;
grub_uint64_t part1_size;
grub_uint8_t disk_uuid[16];
grub_uint8_t disk_signature[4];
grub_uint32_t img_chunk_count;
/* ventoy_img_chunk list */
}ventoy_image_desc;
typedef struct ventoy_img_chunk
{
grub_uint32_t img_start_sector; // sector size: 2KB
@@ -218,6 +243,7 @@ typedef struct ventoy_img_chunk_list
#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
@@ -231,13 +257,13 @@ 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()
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);

View File

@@ -12,19 +12,35 @@ 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 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"
all_modules_legacy="setkey 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 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"
all_modules_uefi="setkey 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"
all_modules_arm64_uefi="setkey blocklist ventoy test regexp newc search 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 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 video video_fb gfxterm_background gfxterm_menu"
all_extra_modules="elf macho offsetio regexp file"
if [ "$1" = "uefi" ]; then
all_modules="$net_modules_uefi $all_modules_uefi $all_extra_modules"
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'
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
#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'
elif [ "$1" = "i386efi" ]; then
all_modules="$net_modules_uefi $all_modules_uefi "
grub-mkimage -v --directory "$VT_DIR/GRUB2/INSTALL/lib/grub/i386-efi" --prefix '(,2)/grub' --output "$VT_DIR/INSTALL/EFI/BOOT/grubia32_real.efi" --format 'i386-efi' --compression 'auto' $all_modules_uefi
elif [ "$1" = "arm64" ]; then
all_modules="$net_modules_uefi $all_modules_arm64_uefi "
grub-mkimage -v --directory "$VT_DIR/GRUB2/INSTALL/lib/grub/arm64-efi" --prefix '(,2)/grub' --output "$VT_DIR/INSTALL/EFI/BOOT/BOOTAA64.EFI" --format 'arm64-efi' --compression 'auto' $all_modules_arm64_uefi
else
all_modules="$net_modules_legacy $all_modules_legacy "
grub-mkimage -v --directory "$VT_DIR/GRUB2/INSTALL/lib/grub/i386-pc" --prefix '(,2)/grub' --output "$VT_DIR/INSTALL/grub/i386-pc/core.img" --format 'i386-pc' --compression 'auto' $all_modules_legacy 'fat' 'part_msdos' 'biosdisk'
#grub-mkimage -v --directory "$VT_DIR/GRUB2/INSTALL/lib/grub/i386-pc" -c "$VT_DIR/LiveCD/GRUB/embed.cfg" --prefix '/EFI/boot' --output "$VT_DIR/LiveCD/GRUB/cdrom.img" --format 'i386-pc-eltorito' --compression 'auto' $all_modules_legacy 'biosdisk' 'iso9660' 'fat' 'part_msdos'
#rm -f $VT_DIR/LiveCD/GRUB/boot_hybrid.img
#cp -a $VT_DIR/GRUB2/INSTALL/lib/grub/i386-pc/boot_hybrid.img $VT_DIR/LiveCD/GRUB/boot_hybrid.img
fi
grub-mknetdir --modules="$all_modules" --net-directory=$VT_DIR/GRUB2/PXE --subdir=grub2 --locales=en@quot || exit 1
@@ -33,17 +49,63 @@ if [ "$1" = "uefi" ]; then
rm -f $VT_DIR/GRUB2/NBP/core.efi
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
rm -rf $VT_DIR/INSTALL/grub/x86_64-efi
mkdir -p $VT_DIR/INSTALL/grub/x86_64-efi
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 ..."
cp -a $VT_DIR/GRUB2/INSTALL/lib/grub/x86_64-efi/$line $VT_DIR/INSTALL/grub/x86_64-efi/
fi
done
elif [ "$1" = "i386efi" ]; then
rm -f $VT_DIR/GRUB2/NBP/core.efi
cp -a $VT_DIR/GRUB2/PXE/grub2/i386-efi/core.efi $VT_DIR/GRUB2/NBP/core.efi || exit 1
rm -rf $VT_DIR/INSTALL/grub/i386-efi
mkdir -p $VT_DIR/INSTALL/grub/i386-efi
cp -a $VT_DIR/GRUB2/PXE/grub2/i386-efi/normal.mod $VT_DIR/INSTALL/grub/i386-efi/normal.mod || exit 1
#copy other modules
ls -1 $VT_DIR/GRUB2/INSTALL/lib/grub/i386-efi/ | egrep '\.(lst|mod)$' | while read line; do
if ! echo $all_modules | grep -q " ${line%.mod} "; then
echo "Copy $line ..."
cp -a $VT_DIR/GRUB2/INSTALL/lib/grub/i386-efi/$line $VT_DIR/INSTALL/grub/i386-efi/
fi
done
elif [ "$1" = "arm64" ]; then
rm -f $VT_DIR/GRUB2/NBP/core.efi
cp -a $VT_DIR/GRUB2/PXE/grub2/arm64-efi/core.efi $VT_DIR/GRUB2/NBP/core.efi || exit 1
rm -rf $VT_DIR/INSTALL/grub/arm64-efi
mkdir -p $VT_DIR/INSTALL/grub/arm64-efi
cp -a $VT_DIR/GRUB2/PXE/grub2/arm64-efi/normal.mod $VT_DIR/INSTALL/grub/arm64-efi/normal.mod || exit 1
#copy other modules
ls -1 $VT_DIR/GRUB2/INSTALL/lib/grub/arm64-efi/ | egrep '\.(lst|mod)$' | while read line; do
if ! echo $all_modules | grep -q " ${line%.mod} "; then
echo "Copy $line ..."
cp -a $VT_DIR/GRUB2/INSTALL/lib/grub/arm64-efi/$line $VT_DIR/INSTALL/grub/arm64-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
for md in $all_extra_modules; do
rm -f $VT_DIR/INSTALL/grub/i386-pc/${md}.mod
cp -a $VT_DIR/GRUB2/INSTALL/lib/grub/i386-pc/${md}.mod $VT_DIR/INSTALL/grub/i386-pc/
done
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

View File

@@ -31,5 +31,13 @@ make -j 16
sh install.sh uefi
#build for IA32 EFI
make distclean
./autogen.sh
./configure --target=i386 --with-platform=efi --prefix=$VT_GRUB_DIR/INSTALL/
make -j 16
sh install.sh i386efi
cd ../../

View File

@@ -1,14 +0,0 @@
#!/bin/bash
/opt/diet32/bin/diet gcc -Os -m32 vtoy_gen_uuid.c -o vtoy_gen_uuid
if [ -e vtoy_gen_uuid ]; then
echo -e '\n############### SUCCESS ###############\n'
rm -f ../INSTALL/tool/vtoy_gen_uuid
cp -a vtoy_gen_uuid ../INSTALL/tool/vtoy_gen_uuid
else
echo -e '\n############### FAILED ################\n'
exit 1
fi

View File

@@ -1,50 +0,0 @@
/******************************************************************************
* vtoy_gen_uuid.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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{
int i;
int fd;
unsigned char uuid[16];
fd = open("/dev/random", O_RDONLY);
if (fd < 0)
{
srand(time(NULL));
for (i = 0; i < 16; i++)
{
uuid[i] = (unsigned char)(rand());
}
}
else
{
read(fd, uuid, 16);
}
fwrite(uuid, 1, 16, stdout);
return 0;
}

BIN
ICON/forums.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
ICON/logo_128.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
ICON/logo_16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
ICON/logo_256.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

BIN
ICON/logo_32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
ICON/logo_48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

BIN
ICON/logo_512.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 KiB

BIN
ICON/logo_64.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

BIN
ICON/logo_72.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

View File

@@ -1,4 +1,4 @@
#!/ventoy/busybox/tmpsh
#!/ventoy/busybox/ash
#************************************************************************************
# Copyright (c) 2020, longpanda <admin@ventoy.net>
#
@@ -36,8 +36,32 @@ export SED=$BUSYBOX_PATH/sed
export SLEEP=$BUSYBOX_PATH/sleep
export HEAD=$BUSYBOX_PATH/head
$BUSYBOX_PATH/tmpxz -d $BUSYBOX_PATH/busybox.xz
if [ -e $BUSYBOX_PATH/32h ]; then
if [ -e $BUSYBOX_PATH/64h ]; then
#this is arm64
$BUSYBOX_PATH/xzminidecaa64 < $BUSYBOX_PATH/busyboxaa64.xz > $BUSYBOX_PATH/busybox
$BUSYBOX_PATH/vtchmodaa64 $BUSYBOX_PATH/busybox
else
#this is x86_64
$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_musl < $BUSYBOX_PATH/busybox64.xz > $BUSYBOX_PATH/busybox
$BUSYBOX_PATH/vtchmod64_musl $BUSYBOX_PATH/busybox
fi
fi
else
$BUSYBOX_PATH/xzminidec32 < $BUSYBOX_PATH/busybox32.xz > $BUSYBOX_PATH/busybox
$BUSYBOX_PATH/vtchmod32 $BUSYBOX_PATH/busybox
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 +78,48 @@ 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/32h ]; then
if [ -e $BUSYBOX_PATH/64h ]; then
echo "Use ARM64 busybox toolkit ..." >>$VTLOG
echo aarch64 > $VTOY_PATH/ventoy_arch
ln -s $BUSYBOX_PATH/xzminidecaa64 $BUSYBOX_PATH/xzminidec
ln -s $VTOY_PATH/tool/dmsetupaa64 $VTOY_PATH/tool/dmsetup
ln -s $VTOY_PATH/tool/lunzipaa64 $VTOY_PATH/tool/lunzip
rm -f $VTOY_PATH/tool/lz4cat $VTOY_PATH/tool/zstdcat
ln -s $VTOY_PATH/tool/lz4cataa64 $VTOY_PATH/tool/lz4cat
ln -s $VTOY_PATH/tool/zstdcataa64 $VTOY_PATH/tool/zstdcat
else
echo "Use x86_64 busybox toolkit ..." >>$VTLOG
echo x86_64 > $VTOY_PATH/ventoy_arch
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
rm -f $VTOY_PATH/tool/lz4cat $VTOY_PATH/tool/zstdcat
ln -s $VTOY_PATH/tool/lz4cat64 $VTOY_PATH/tool/lz4cat
ln -s $VTOY_PATH/tool/zstdcat64 $VTOY_PATH/tool/zstdcat
fi
else
echo "Use i386 busybox toolkit ..." >>$VTLOG
echo i386 > $VTOY_PATH/ventoy_arch
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
fi
rm -f *.xz

BIN
IMG/cpio/ventoy/busybox/64h Normal file

Binary file not shown.

BIN
IMG/cpio/ventoy/busybox/a64 Normal file

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More