Compare commits
83 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
433d854aab | ||
|
4cb9134e5c | ||
|
faceaf4267 | ||
|
37edd5a349 | ||
|
ed0f8721d7 | ||
|
d80a008c04 | ||
|
036e9cc167 | ||
|
26258653b7 | ||
|
754e754412 | ||
|
5af01de7c2 | ||
|
f9763a44b2 | ||
|
d063dbb7f2 | ||
|
89938e3c78 | ||
|
85840f626b | ||
|
7d1507906d | ||
|
0f8478fbe1 | ||
|
a6d3ecc7a9 | ||
|
5817b8b7b0 | ||
|
8493715fb4 | ||
|
3c46432d6f | ||
|
88dcceeabc | ||
|
ef204263ad | ||
|
e08e6705cf | ||
|
a8b2fdccc7 | ||
|
85348956df | ||
|
aa0a2ed067 | ||
|
49ceaa0f61 | ||
|
23986d742d | ||
|
039e68400d | ||
|
e384dad4d0 | ||
|
dcb3264519 | ||
|
4fda20d844 | ||
|
b32cf97f1f | ||
|
f7b35f371b | ||
|
49ca1e05a4 | ||
|
9ecbff9ce6 | ||
|
1d034f0a24 | ||
|
0ddc76a3aa | ||
|
a1ddade13c | ||
|
b925bbdeec | ||
|
e91b315f09 | ||
|
1cbe4c81b4 | ||
|
42990058ed | ||
|
171667c547 | ||
|
a5c706511b | ||
|
785255b65f | ||
|
176c819d10 | ||
|
8f2bf03084 | ||
|
4408be5cf0 | ||
|
74154ad9a3 | ||
|
43fcd4f262 | ||
|
be35990666 | ||
|
ad3db3dfcb | ||
|
227264f208 | ||
|
1f37663285 | ||
|
8cde5a4898 | ||
|
c8e86938fe | ||
|
7a0b2d945e | ||
|
5089fda07d | ||
|
f77ba141fd | ||
|
6d1ace0570 | ||
|
a2d732c170 | ||
|
a54b6f692c | ||
|
73c196a823 | ||
|
487ffc6795 | ||
|
ad7322cb0a | ||
|
ef40780f20 | ||
|
f0d59949e5 | ||
|
89c1ab55f1 | ||
|
1e4965cb24 | ||
|
ac0f68f90b | ||
|
50aa5d3823 | ||
|
e80871a31e | ||
|
0997342607 | ||
|
c4a79e68e1 | ||
|
5f60eae6ee | ||
|
90fa7adc84 | ||
|
b0c321dfc8 | ||
|
efa7a942ac | ||
|
f352003913 | ||
|
2aae096c2a | ||
|
5d0fe69b25 | ||
|
965417970b |
12
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: ['https://www.ventoy.net/en/donation.html'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
@@ -2,7 +2,8 @@ Build a static linked, small dmsetup tool
|
||||
|
||||
======== Source Code ========
|
||||
use an old version of dmsetup
|
||||
xxx/centos-vault/5.3/os/SRPMS/device-mapper-1.02.28-2.el5.src.rpm
|
||||
http://vault.centos.org/5.3/os/SRPMS/device-mapper-1.02.28-2.el5.src.rpm
|
||||
https://www.fefe.de/dietlibc/dietlibc-0.34.tar.xz
|
||||
|
||||
======== Build Envrioment ========
|
||||
build for 32bit, static linked with dietlibc
|
||||
|
211
DOC/BuildVentoyFromSource.txt
Normal file
@@ -0,0 +1,211 @@
|
||||
|
||||
==========================================
|
||||
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.
|
||||
|
||||
1.1 Install CentOS 7.8
|
||||
I use CentOS-7-x86_64-Everything-2003.iso and select Minimal install
|
||||
|
||||
1.2 Install Packages
|
||||
yum install \
|
||||
libXpm net-tools bzip2 wget vim gcc gcc-c++ samba dos2unix glibc-devel glibc.i686 glibc-devel.i686 \
|
||||
mpfr.i686 mpfr-devel.i686 zlib.i686 rsync autogen autoconf automake libtool gettext* bison binutils \
|
||||
flex device-mapper-devel SDL libpciaccess libusb freetype freetype-devel gnu-free-* qemu-* virt-* \
|
||||
libvirt* vte* NetworkManager-bluetooth brlapi fuse-devel dejavu* gnu-efi* pesign shim \
|
||||
iscsi-initiator-utils grub2-tools zip nasm acpica-tools glibc-static zlib-static
|
||||
|
||||
|
||||
|
||||
==========================================
|
||||
2. Download Source Code
|
||||
==========================================
|
||||
2.1 Download Ventoy source code from github and decompress it.
|
||||
Next I assume that you have unzipped the code into the /home directory (check /home/Ventoy-master/README.md file for the directory level).
|
||||
|
||||
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://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
|
||||
|
||||
|
||||
|
||||
==========================================
|
||||
3. All in one script
|
||||
==========================================
|
||||
I have made the whole build process in all_in_one.sh, you can run this script to build and pack ventoy.
|
||||
If you want to compile a certain part separately, you can continue to refer to the later chapters of this text.
|
||||
|
||||
cd /home/Ventoy-master/INSTALL
|
||||
sh all_in_one.sh
|
||||
|
||||
It should be noted that, some part of Ventoy has 32bit&64bit version (like 4.9 4.10 4.11 follows)
|
||||
all_in_one.sh only build 64bit version of them, if you want to rebuild the 32bit verison. You should create a 32bit CentOS environment and build them.
|
||||
Fortunately these parts are few modified, you only need to build once or you can directly use the binary I have built.
|
||||
|
||||
Besides, after a fully compile and pack, you can only build the part you modified (for example grub2) and run ventoy_pack.sh to generate the package.
|
||||
|
||||
|
||||
|
||||
==========================================
|
||||
4. Build every part of Ventoy
|
||||
==========================================
|
||||
4.1 == Build grub2 ==
|
||||
cd /home/Ventoy-master/GRUB2
|
||||
sh buildgrub.sh
|
||||
|
||||
4.2 == Build ipxe.krn ==
|
||||
cd /home/Ventoy-master/IPXE
|
||||
sh buildipxe.sh
|
||||
|
||||
4.3 == Build Ventoy2Disk.exe ==
|
||||
Ventoy2Disk.exe is the installer in Windows platform. And it must be built in Windows with Microsoft Visual Studio (2013+).
|
||||
Open /home/Ventoy-master/Ventoy2Disk/Ventoy2Disk.sln with Visual Studio and build it.
|
||||
|
||||
4.4 == Build vtoyjump64.exe/vtoyjump32.exe ==
|
||||
vtoyjump64.exe/vtoyjump32.exe is used to mount iso file in windows PE. You should install Microsoft Visual Studio (2013+) to build it.
|
||||
Open /home/Ventoy-master/vtoyjump/vtoyjump.sln with Visual Studio and build it (64&32).
|
||||
|
||||
4.5 == Build dmsetup ==
|
||||
Please refer to DMSETUP/build.txt
|
||||
|
||||
4.6 == Build ventoy_x64.efi ==
|
||||
cd /home/Ventoy-master/EDK2
|
||||
sh buildedk.sh
|
||||
|
||||
4.7 == Build VtoyTool ==
|
||||
cd /home/Ventoy-master/VtoyTool
|
||||
sh build.sh
|
||||
|
||||
4.8 == Build vtoyfat ==
|
||||
cd /home/Ventoy-master/vtoyfat/fat_io_lib
|
||||
sh buildlib.sh
|
||||
cd /home/Ventoy-master/vtoyfat
|
||||
sh build.sh
|
||||
|
||||
4.9 == Build exfat-util ==
|
||||
cd /home/Ventoy-master/ExFAT
|
||||
sh buidlibfuse.sh
|
||||
sh buidexfat.sh
|
||||
|
||||
After that, copy EXFAT/shared/mkexfatfs ===> /home/Ventoy-master/INSTALL/tool/mkexfatfs_64
|
||||
After that, copy EXFAT/shared/mount.exfat-fuse ===> /home/Ventoy-master/INSTALL/tool/mount.exfat-fuse_64
|
||||
|
||||
Use the same build step to build exfat-util 32bit in a 32bit CentOS system and get mkexfatfs_32 and mount.exfat-fuse_32
|
||||
|
||||
4.10 == Build vtoy_fuse_iso_64/vtoy_fuse_iso_32 ==
|
||||
cd /home/Ventoy-master/FUSEISO
|
||||
sh build_libfuse.sh
|
||||
sh build.sh
|
||||
|
||||
Use the same build step to build in a 32bit CentOS system and get vtoy_fuse_iso_32
|
||||
|
||||
4.11 == Build unsquashfs_64/unsquashfs_32 ==
|
||||
cd /home/Ventoy-master/SQUASHFS/SRC
|
||||
sh build_lz4.sh
|
||||
sh build_lzma.sh
|
||||
sh build_lzo.sh
|
||||
sh build_zstd.sh
|
||||
|
||||
cd /home/Ventoy-master/SQUASHFS/squashfs-tools-4.4/squashfs-tools
|
||||
sh build.sh
|
||||
|
||||
Use the same build step to build in a 32bit CentOS system and get unsquashfs_32
|
||||
|
||||
4.12 == Build vblade_64/vblade_32 ==
|
||||
cd /home/Ventoy-master/VBLADE/vblade-master
|
||||
sh build.sh
|
||||
|
||||
4.13 == Build zstdcat ==
|
||||
Please refer to ZSTD/build.txt
|
||||
|
||||
4.14 == Build vtoy_gen_uuid ==
|
||||
cd /home/Ventoy-master/GenUUID
|
||||
sh build.sh
|
||||
|
||||
4.15 == Build xzminidec ==
|
||||
cd /home/Ventoy-master/xz-embedded-20130513/userspace
|
||||
make -f ventoy_makefile
|
||||
strip --strip-all xzminidec
|
||||
|
||||
4.16 == 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)
|
||||
|
||||
|
||||
|
||||
==========================================
|
||||
5. Binaries
|
||||
==========================================
|
||||
There some binaries in Ventoy install package. These files are downloaded from other open source project's website, such as busybox.
|
||||
Here is the list of the binaries, their SHA-256 and the download urls:
|
||||
|
||||
5.1 IMG/cpio/ventoy/tool/lz4cat
|
||||
https://create.stephan-brumme.com/smallz4 smallz4cat-x32-v1.4
|
||||
SHA-256: 13d293ddeedb469f51da41167f79b2cbdb904e681716f6e6191b233dbb162438
|
||||
|
||||
5.2 IMG/cpio/ventoy/tool/ar
|
||||
https://busybox.net/downloads/binaries/1.30.0-i686 busybox_AR
|
||||
SHA-256: f29b7d81a983c0c85d22496f4a833c18f2528a1b666eb7d47c93084c1ed66ae0
|
||||
|
||||
5.3 IMG/cpio/ventoy/tool/inotifyd
|
||||
https://busybox.net/downloads/binaries/1.30.0-i686 busybox_INOTIFYD
|
||||
SHA-256: 3532162a8695e91a1ed9ddea28b2cb22259a90e93d5d9c4a517b6c36842c686f
|
||||
|
||||
5.4 IMG/cpio/ventoy/busybox/tmpsh
|
||||
https://busybox.net/downloads/binaries/1.27.1-i686 busybox_ASH
|
||||
SHA-256: 44a6274bca580c2758ffc173fc76d18bb855b1fe8dcf70efd9ee75cbd57dee97
|
||||
|
||||
5.5 IMG/cpio/ventoy/busybox/tmpxz
|
||||
https://busybox.net/downloads/binaries/1.27.1-i686 busybox_XZ
|
||||
SHA-256: f6cdb6293680424c29b89bde0685ca27f455166c9b302cd6082ef90681456291
|
||||
|
||||
5.6 INSTALL/tool/xzcat
|
||||
https://busybox.net/downloads/binaries/1.30.0-i686/ busybox_XZCAT
|
||||
SHA-256: 7399db642c2beaf52a16ab5264ffc55cfd1ff5699a524f63e5d48edf84e20f44
|
||||
|
||||
5.7 INSTALL/tool/hexdump
|
||||
https://busybox.net/downloads/binaries/1.30.0-i686/ busybox_HEXDUMP
|
||||
SHA-256: cde08b6a2cf5ad914f05203e18e3f7c2ed6060a63604e3d75536f19b55e8e0af
|
||||
|
||||
5.8 imdisk
|
||||
download http://www.ltr-data.se/files/imdiskinst.exe and extract it by 7zip.
|
||||
|
||||
INSTALL/ventoy/imdisk/64/imdisk.sys --> sys/amd64/imdisk.sys SHA-256: 6702202220268787e361f5a82dae53362c8e6c6dcd240bb01b44dd77ae0788da
|
||||
INSTALL/ventoy/imdisk/64/imdisk.exe --> cli/amd64/imdisk.exe SHA-256: 9759175380af836869443e5f21ce2e33022125d154bc6b3d1c04dc36b190de04
|
||||
INSTALL/ventoy/imdisk/64/imdisk.cpl --> cpl/amd64/imdisk.cpl SHA-256: aea2ebbea2b073c947263744962af8a3eab025ff4c9d825c543e380e738a4c99
|
||||
|
||||
INSTALL/ventoy/imdisk/32/imdisk.sys --> sys/i386/imdisk.sys SHA-256: a94caec2f71a924d6a914c093ad4b905d7cfdea3f515ed48aaa8c3950b2dc191
|
||||
INSTALL/ventoy/imdisk/32/imdisk.exe --> cli/i386/imdisk.exe SHA-256: 33b53858e2139704cf603b115a3e5e1dfd4daeaaed4d3e03c633f2df3b55dbaa
|
||||
INSTALL/ventoy/imdisk/32/imdisk.cpl --> cpl/i386/imdisk.cpl SHA-256: b781d3e2d286ac8bf548f44e50cbbb3fe78203296e41e4d2e73b407668f88f2d
|
||||
|
||||
5.9 INSTALL/ventoy/memdisk
|
||||
https://mirrors.edge.kernel.org/pub/linux/utils/boot/syslinux/syslinux-6.03.tar.gz
|
||||
decompress it and memdisk is at syslinux-6.03/bios/memdisk/memdisk
|
||||
SHA-256: 3f6cd656b8a14109cd3f906fee2dd2e75418f983a5e1bfdb64f44f7765588cbb
|
||||
|
||||
|
||||
5.10 UEFIinSecureBoot
|
||||
https://github.com/ValdikSS/Super-UEFIinSecureBoot-Disk/releases Super-UEFIinSecureBoot-Disk_minimal_v3.zip
|
||||
unzip it and get Super-UEFIinSecureBoot-Disk_minimal.img, extract the img by 7zip.
|
||||
|
||||
INSTALL/EFI/BOOT/BOOTX64.EFI --> EFI/BOOT/BOOTX64.EFI SHA-256: 475552c7476ad45e42344eee8b30d44c264d200ac2468428aa86fc8795fb6e34
|
||||
INSTALL/EFI/BOOT/grubx64.efi --> EFI/BOOT/grubx64.efi SHA-256: 25d858157349dc52fa70f3cdf5c62fe1e0bae37ddfc3a6b6528af9a3c745775f
|
||||
INSTALL/EFI/BOOT/MokManager.efi --> EFI/BOOT/MokManager.efi SHA-256: 3bf1f46cee0832355c7dd1dba880dea9bcaa78cc44375a1559d43bc9db18933b
|
||||
|
||||
|
||||
5.11 INSTALL/tool/ash
|
||||
https://busybox.net/downloads/binaries/1.31.0-i686-uclibc/ busybox_ASH
|
||||
SHA-256: 2943f02f85fee0c9551aec47110a558a73f919c032b3c51e56d6f197b5ec4d7b
|
||||
|
||||
5.12 7za.exe
|
||||
download from https://www.7-zip.org/a/7z1900-extra.7z
|
||||
ISNTALL/ventoy/7z/64/7za.exe SHA-256: 8117e40ee7f824f63373a4f5625bb62749f69159d0c449b3ce2f35aad3b83549
|
||||
ISNTALL/ventoy/7z/32/7za.exe SHA-256: ea308c76a2f927b160a143d94072b0dce232e04b751f0c6432a94e05164e716d
|
||||
|
||||
|
||||
|
34
DOC/installdietlibc.sh
Normal file
@@ -0,0 +1,34 @@
|
||||
#!/bin/bash
|
||||
|
||||
if ! [ -f ./dietlibc-0.34.tar.xz ]; then
|
||||
echo "No dietlibc-0.34.tar.xz found ..."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -rf /opt/diet32
|
||||
rm -rf /opt/diet64
|
||||
|
||||
tar -xvf dietlibc-0.34.tar.xz
|
||||
cd dietlibc-0.34
|
||||
|
||||
prefix=/opt/diet64 make -j 4
|
||||
prefix=/opt/diet64 make install 2>/dev/null
|
||||
|
||||
cd ..
|
||||
rm -rf dietlibc-0.34
|
||||
|
||||
tar -xvf dietlibc-0.34.tar.xz
|
||||
cd dietlibc-0.34
|
||||
|
||||
sed "s/MYARCH:=.*/MYARCH=i386/" -i Makefile
|
||||
sed "s/CC=gcc/CC=gcc -m32/" -i Makefile
|
||||
|
||||
prefix=/opt/diet32 make -j 4
|
||||
prefix=/opt/diet32 make install 2>/dev/null
|
||||
|
||||
cd ..
|
||||
rm -rf dietlibc-0.34
|
||||
|
||||
echo ""
|
||||
echo " ================ success ==============="
|
||||
echo ""
|
17
Dockerfile
Normal file
@@ -0,0 +1,17 @@
|
||||
FROM centos:7
|
||||
|
||||
RUN yum -y install \
|
||||
libXpm net-tools bzip2 wget vim gcc gcc-c++ samba dos2unix glibc-devel glibc.i686 glibc-devel.i686 \
|
||||
mpfr.i686 mpfr-devel.i686 zlib.i686 rsync autogen autoconf automake libtool gettext* bison binutils \
|
||||
flex device-mapper-devel SDL libpciaccess libusb freetype freetype-devel gnu-free-* qemu-* virt-* \
|
||||
libvirt* vte* NetworkManager-bluetooth brlapi fuse-devel dejavu* gnu-efi* pesign shim \
|
||||
iscsi-initiator-utils grub2-tools zip nasm acpica-tools glibc-static zlib-static
|
||||
|
||||
CMD cd /ventoy \
|
||||
&& wget -P DOC/ https://www.fefe.de/dietlibc/dietlibc-0.34.tar.xz \
|
||||
&& wget -P GRUB2/ https://ftp.gnu.org/gnu/grub/grub-2.04.tar.xz \
|
||||
&& wget -O EDK2/edk2-edk2-stable201911.zip https://codeload.github.com/tianocore/edk2/zip/edk2-stable201911 \
|
||||
&& wget -O ExFAT/exfat-1.3.0.zip https://codeload.github.com/relan/exfat/zip/v1.3.0 \
|
||||
&& wget -O ExFAT/libfuse-fuse-2.9.9.zip https://codeload.github.com/libfuse/libfuse/zip/fuse-2.9.9 \
|
||||
&& cd INSTALL && ls -la && sh all_in_one.sh
|
||||
|
@@ -1,8 +0,0 @@
|
||||
|
||||
========== About Source Code =============
|
||||
Ventoy add an UEFI application module in MdeModulePkg, so I only put the module's source code here.
|
||||
You can download the EDK2 code from https://github.com/tianocore/edk2 and merge the code together.
|
||||
|
||||
|
||||
========== Build =============
|
||||
Follow the EDK2's build instructions
|
33
EDK2/buildedk.sh
Normal file
@@ -0,0 +1,33 @@
|
||||
#!/bin/sh
|
||||
|
||||
rm -rf edk2-edk2-stable201911
|
||||
|
||||
unzip edk2-edk2-stable201911.zip
|
||||
|
||||
/bin/cp -a ./edk2_mod/edk2-edk2-stable201911 ./
|
||||
|
||||
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
|
||||
|
||||
rm -f $VTEFI_PATH
|
||||
rm -f $DST_PATH
|
||||
|
||||
make -j 4 -C BaseTools/
|
||||
|
||||
source ./edksetup.sh
|
||||
build -p MdeModulePkg/MdeModulePkg.dsc -a X64 -b RELEASE -t GCC48
|
||||
|
||||
if [ -e $VTEFI_PATH ]; then
|
||||
echo -e '\n\n====================== SUCCESS ========================\n\n'
|
||||
cp -a $VTEFI_PATH $DST_PATH
|
||||
cd ..
|
||||
else
|
||||
echo -e '\n\n====================== FAILED ========================\n\n'
|
||||
cd ..
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
|
@@ -36,34 +36,31 @@
|
||||
#include <Protocol/SimpleFileSystem.h>
|
||||
#include <Ventoy.h>
|
||||
|
||||
UINTN g_iso_buf_size = 0;
|
||||
BOOLEAN gMemdiskMode = FALSE;
|
||||
BOOLEAN gDebugPrint = FALSE;
|
||||
BOOLEAN gLoadIsoEfi = FALSE;
|
||||
ventoy_ram_disk g_ramdisk_param;
|
||||
ventoy_chain_head *g_chain;
|
||||
ventoy_img_chunk *g_chunk;
|
||||
UINT8 *g_os_param_reserved;
|
||||
UINT32 g_img_chunk_num;
|
||||
ventoy_override_chunk *g_override_chunk;
|
||||
UINT32 g_override_chunk_num;
|
||||
ventoy_virt_chunk *g_virt_chunk;
|
||||
UINT32 g_virt_chunk_num;
|
||||
vtoy_block_data gBlockData;
|
||||
ventoy_sector_flag *g_sector_flag = NULL;
|
||||
UINT32 g_sector_flag_num = 0;
|
||||
static grub_env_get_pf grub_env_get = NULL;
|
||||
|
||||
EFI_FILE_OPEN g_original_fopen = NULL;
|
||||
EFI_FILE_CLOSE g_original_fclose = NULL;
|
||||
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME g_original_open_volume = NULL;
|
||||
|
||||
ventoy_grub_param_file_replace *g_file_replace_list = NULL;
|
||||
ventoy_efi_file_replace g_efi_file_replace;
|
||||
|
||||
CHAR16 gFirstTryBootFile[256] = {0};
|
||||
|
||||
CONST CHAR16 gIso9660EfiDriverPath[] = ISO9660_EFI_DRIVER_PATH;
|
||||
|
||||
BOOLEAN g_fix_windows_1st_cdrom_issue = FALSE;
|
||||
|
||||
STATIC BOOLEAN g_hook_keyboard = FALSE;
|
||||
|
||||
CHAR16 gFirstTryBootFile[256] = {0};
|
||||
|
||||
/* Boot filename */
|
||||
UINTN gBootFileStartIndex = 1;
|
||||
CONST CHAR16 *gEfiBootFileName[] =
|
||||
@@ -76,9 +73,6 @@ CONST CHAR16 *gEfiBootFileName[] =
|
||||
L"\\efi\\boot\\bootx64.efi",
|
||||
};
|
||||
|
||||
/* EFI block device vendor device path GUID */
|
||||
EFI_GUID gVtoyBlockDevicePathGuid = VTOY_BLOCK_DEVICE_PATH_GUID;
|
||||
|
||||
VOID EFIAPI VtoyDebug(IN CONST CHAR8 *Format, ...)
|
||||
{
|
||||
VA_LIST Marker;
|
||||
@@ -204,6 +198,13 @@ static void EFIAPI ventoy_dump_chain(ventoy_chain_head *chain)
|
||||
debug("os_param->vtoy_img_size=<%llu>", chain->os_param.vtoy_img_size);
|
||||
debug("os_param->vtoy_img_location_addr=<0x%llx>", chain->os_param.vtoy_img_location_addr);
|
||||
debug("os_param->vtoy_img_location_len=<%u>", chain->os_param.vtoy_img_location_len);
|
||||
debug("os_param->vtoy_reserved=<%u %u %u %u %u>",
|
||||
g_os_param_reserved[0],
|
||||
g_os_param_reserved[1],
|
||||
g_os_param_reserved[2],
|
||||
g_os_param_reserved[3],
|
||||
g_os_param_reserved[4]
|
||||
);
|
||||
|
||||
ventoy_debug_pause();
|
||||
|
||||
@@ -224,6 +225,70 @@ static void EFIAPI ventoy_dump_chain(ventoy_chain_head *chain)
|
||||
ventoy_dump_virt_chunk(chain);
|
||||
}
|
||||
|
||||
static int ventoy_update_image_location(ventoy_os_param *param)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
UINT8 chksum = 0;
|
||||
unsigned int i;
|
||||
unsigned int length;
|
||||
UINTN address = 0;
|
||||
void *buffer = NULL;
|
||||
ventoy_image_location *location = NULL;
|
||||
ventoy_image_disk_region *region = NULL;
|
||||
ventoy_img_chunk *chunk = g_chunk;
|
||||
|
||||
length = sizeof(ventoy_image_location) + (g_img_chunk_num - 1) * sizeof(ventoy_image_disk_region);
|
||||
|
||||
Status = gBS->AllocatePool(EfiRuntimeServicesData, length + 4096 * 2, &buffer);
|
||||
if (EFI_ERROR(Status) || NULL == buffer)
|
||||
{
|
||||
debug("Failed to allocate runtime pool %r\n", Status);
|
||||
return 1;
|
||||
}
|
||||
|
||||
address = (UINTN)buffer;
|
||||
|
||||
if (address % 4096)
|
||||
{
|
||||
address += 4096 - (address % 4096);
|
||||
}
|
||||
|
||||
param->chksum = 0;
|
||||
param->vtoy_img_location_addr = address;
|
||||
param->vtoy_img_location_len = length;
|
||||
|
||||
/* update check sum */
|
||||
for (i = 0; i < sizeof(ventoy_os_param); i++)
|
||||
{
|
||||
chksum += *((UINT8 *)param + i);
|
||||
}
|
||||
param->chksum = (chksum == 0) ? 0 : (UINT8)(0x100 - chksum);
|
||||
|
||||
location = (ventoy_image_location *)(unsigned long)(param->vtoy_img_location_addr);
|
||||
if (NULL == location)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
CopyMem(&location->guid, ¶m->guid, sizeof(ventoy_guid));
|
||||
location->image_sector_size = 2048;
|
||||
location->disk_sector_size = g_chain->disk_sector_size;
|
||||
location->region_count = g_img_chunk_num;
|
||||
|
||||
region = location->regions;
|
||||
|
||||
for (i = 0; i < g_img_chunk_num; i++)
|
||||
{
|
||||
region->image_sector_count = chunk->img_end_sector - chunk->img_start_sector + 1;
|
||||
region->image_start_sector = chunk->img_start_sector;
|
||||
region->disk_start_sector = chunk->disk_start_sector;
|
||||
region++;
|
||||
chunk++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EFI_HANDLE EFIAPI ventoy_get_parent_handle(IN EFI_DEVICE_PATH_PROTOCOL *pDevPath)
|
||||
{
|
||||
EFI_HANDLE Handle = NULL;
|
||||
@@ -258,280 +323,6 @@ EFI_HANDLE EFIAPI ventoy_get_parent_handle(IN EFI_DEVICE_PATH_PROTOCOL *pDevPath
|
||||
return Handle;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_block_io_reset
|
||||
(
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN BOOLEAN ExtendedVerification
|
||||
)
|
||||
{
|
||||
(VOID)This;
|
||||
(VOID)ExtendedVerification;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
STATIC EFI_STATUS EFIAPI ventoy_read_iso_sector
|
||||
(
|
||||
IN UINT64 Sector,
|
||||
IN UINTN Count,
|
||||
OUT 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;
|
||||
UINT64 OverrideStart = 0;
|
||||
UINT64 OverrideEnd= 0;
|
||||
UINT8 *pCurBuf = (UINT8 *)Buffer;
|
||||
ventoy_img_chunk *pchunk = g_chunk;
|
||||
ventoy_override_chunk *pOverride = g_override_chunk;
|
||||
EFI_BLOCK_IO_PROTOCOL *pRawBlockIo = gBlockData.pRawBlockIo;
|
||||
|
||||
debug("read 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
|
||||
{
|
||||
MapLba = (Sector - pchunk->img_start_sector) * 2048 / g_chain->disk_sector_size + pchunk->disk_start_sector;
|
||||
}
|
||||
|
||||
secLeft = pchunk->img_end_sector + 1 - Sector;
|
||||
secRead = (Count < secLeft) ? Count : secLeft;
|
||||
|
||||
Status = pRawBlockIo->ReadBlocks(pRawBlockIo, pRawBlockIo->Media->MediaId,
|
||||
MapLba, secRead * 2048, pCurBuf);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
debug("Raw disk read block failed %r", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Count -= secRead;
|
||||
Sector += secRead;
|
||||
pCurBuf += secRead * 2048;
|
||||
}
|
||||
}
|
||||
|
||||
if (ReadStart > g_chain->real_img_size_in_bytes)
|
||||
{
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/* override data */
|
||||
pCurBuf = (UINT8 *)Buffer;
|
||||
for (i = 0; i < g_override_chunk_num; i++, pOverride++)
|
||||
{
|
||||
OverrideStart = pOverride->img_offset;
|
||||
OverrideEnd = pOverride->img_offset + pOverride->override_size;
|
||||
|
||||
if (OverrideStart >= ReadEnd || ReadStart >= OverrideEnd)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ReadStart <= OverrideStart)
|
||||
{
|
||||
if (ReadEnd <= OverrideEnd)
|
||||
{
|
||||
CopyMem(pCurBuf + OverrideStart - ReadStart, pOverride->override_data, ReadEnd - OverrideStart);
|
||||
}
|
||||
else
|
||||
{
|
||||
CopyMem(pCurBuf + OverrideStart - ReadStart, pOverride->override_data, pOverride->override_size);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ReadEnd <= OverrideEnd)
|
||||
{
|
||||
CopyMem(pCurBuf, pOverride->override_data + ReadStart - OverrideStart, ReadEnd - ReadStart);
|
||||
}
|
||||
else
|
||||
{
|
||||
CopyMem(pCurBuf, pOverride->override_data + ReadStart - OverrideStart, OverrideEnd - ReadStart);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_block_io_ramdisk_read
|
||||
(
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSize,
|
||||
OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
//debug("### ventoy_block_io_ramdisk_read sector:%u count:%u", (UINT32)Lba, (UINT32)BufferSize / 2048);
|
||||
|
||||
(VOID)This;
|
||||
(VOID)MediaId;
|
||||
|
||||
CopyMem(Buffer, (char *)g_chain + (Lba * 2048), BufferSize);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_block_io_read
|
||||
(
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSize,
|
||||
OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
UINT32 i = 0;
|
||||
UINT32 j = 0;
|
||||
UINT32 lbacount = 0;
|
||||
UINT32 secNum = 0;
|
||||
UINT64 offset = 0;
|
||||
EFI_LBA curlba = 0;
|
||||
EFI_LBA lastlba = 0;
|
||||
UINT8 *lastbuffer;
|
||||
ventoy_sector_flag *cur_flag;
|
||||
ventoy_virt_chunk *node;
|
||||
|
||||
//debug("### ventoy_block_io_read sector:%u count:%u", (UINT32)Lba, (UINT32)BufferSize / 2048);
|
||||
|
||||
secNum = BufferSize / 2048;
|
||||
offset = Lba * 2048;
|
||||
|
||||
if (offset + BufferSize < g_chain->real_img_size_in_bytes)
|
||||
{
|
||||
return ventoy_read_iso_sector(Lba, secNum, Buffer);
|
||||
}
|
||||
|
||||
if (secNum > g_sector_flag_num)
|
||||
{
|
||||
cur_flag = AllocatePool(secNum * sizeof(ventoy_sector_flag));
|
||||
if (NULL == cur_flag)
|
||||
{
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
FreePool(g_sector_flag);
|
||||
g_sector_flag = cur_flag;
|
||||
g_sector_flag_num = secNum;
|
||||
}
|
||||
|
||||
for (curlba = Lba, cur_flag = g_sector_flag, j = 0; j < secNum; j++, curlba++, cur_flag++)
|
||||
{
|
||||
cur_flag->flag = 0;
|
||||
for (node = g_virt_chunk, i = 0; i < g_virt_chunk_num; i++, node++)
|
||||
{
|
||||
if (curlba >= node->mem_sector_start && curlba < node->mem_sector_end)
|
||||
{
|
||||
CopyMem((UINT8 *)Buffer + j * 2048,
|
||||
(char *)g_virt_chunk + node->mem_sector_offset + (curlba - node->mem_sector_start) * 2048,
|
||||
2048);
|
||||
cur_flag->flag = 1;
|
||||
break;
|
||||
}
|
||||
else if (curlba >= node->remap_sector_start && curlba < node->remap_sector_end)
|
||||
{
|
||||
cur_flag->remap_lba = node->org_sector_start + curlba - node->remap_sector_start;
|
||||
cur_flag->flag = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (curlba = Lba, cur_flag = g_sector_flag, j = 0; j < secNum; j++, curlba++, cur_flag++)
|
||||
{
|
||||
if (cur_flag->flag == 2)
|
||||
{
|
||||
if (lastlba == 0)
|
||||
{
|
||||
lastbuffer = (UINT8 *)Buffer + j * 2048;
|
||||
lastlba = cur_flag->remap_lba;
|
||||
lbacount = 1;
|
||||
}
|
||||
else if (lastlba + lbacount == cur_flag->remap_lba)
|
||||
{
|
||||
lbacount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
ventoy_read_iso_sector(lastlba, lbacount, lastbuffer);
|
||||
lastbuffer = (UINT8 *)Buffer + j * 2048;
|
||||
lastlba = cur_flag->remap_lba;
|
||||
lbacount = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lbacount > 0)
|
||||
{
|
||||
ventoy_read_iso_sector(lastlba, lbacount, lastbuffer);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_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)Lba;
|
||||
(VOID)BufferSize;
|
||||
(VOID)Buffer;
|
||||
return EFI_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_block_io_flush(IN EFI_BLOCK_IO_PROTOCOL *This)
|
||||
{
|
||||
(VOID)This;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_fill_device_path(VOID)
|
||||
{
|
||||
UINTN NameLen = 0;
|
||||
UINT8 TmpBuf[128] = {0};
|
||||
VENDOR_DEVICE_PATH *venPath = NULL;
|
||||
|
||||
venPath = (VENDOR_DEVICE_PATH *)TmpBuf;
|
||||
NameLen = StrSize(VTOY_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, &gVtoyBlockDevicePathGuid, sizeof(EFI_GUID));
|
||||
CopyMem(venPath + 1, VTOY_BLOCK_DEVICE_PATH_NAME, NameLen);
|
||||
|
||||
gBlockData.Path = AppendDevicePathNode(NULL, (EFI_DEVICE_PATH_PROTOCOL *)TmpBuf);
|
||||
gBlockData.DevicePathCompareLen = sizeof(VENDOR_DEVICE_PATH) + NameLen;
|
||||
|
||||
debug("gBlockData.Path=<%s>\n", ConvertDevicePathToText(gBlockData.Path, FALSE, FALSE));
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_save_ramdisk_param(VOID)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
@@ -545,7 +336,7 @@ EFI_STATUS EFIAPI ventoy_save_ramdisk_param(VOID)
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_del_ramdisk_param(VOID)
|
||||
EFI_STATUS EFIAPI ventoy_delete_ramdisk_param(VOID)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_GUID VarGuid = VENTOY_GUID;
|
||||
@@ -559,7 +350,7 @@ EFI_STATUS EFIAPI ventoy_del_ramdisk_param(VOID)
|
||||
}
|
||||
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_set_variable(VOID)
|
||||
EFI_STATUS EFIAPI ventoy_save_variable(VOID)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_GUID VarGuid = VENTOY_GUID;
|
||||
@@ -585,56 +376,7 @@ EFI_STATUS EFIAPI ventoy_delete_variable(VOID)
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_install_blockio(IN EFI_HANDLE ImageHandle, IN UINT64 ImgSize)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_BLOCK_IO_PROTOCOL *pBlockIo = &(gBlockData.BlockIo);
|
||||
|
||||
ventoy_fill_device_path();
|
||||
|
||||
gBlockData.Media.BlockSize = 2048;
|
||||
gBlockData.Media.LastBlock = ImgSize / 2048 - 1;
|
||||
gBlockData.Media.ReadOnly = TRUE;
|
||||
gBlockData.Media.MediaPresent = 1;
|
||||
gBlockData.Media.LogicalBlocksPerPhysicalBlock = 1;
|
||||
|
||||
pBlockIo->Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3;
|
||||
pBlockIo->Media = &(gBlockData.Media);
|
||||
pBlockIo->Reset = ventoy_block_io_reset;
|
||||
|
||||
if (gMemdiskMode)
|
||||
{
|
||||
pBlockIo->ReadBlocks = ventoy_block_io_ramdisk_read;
|
||||
}
|
||||
else
|
||||
{
|
||||
pBlockIo->ReadBlocks = ventoy_block_io_read;
|
||||
}
|
||||
|
||||
pBlockIo->WriteBlocks = ventoy_block_io_write;
|
||||
pBlockIo->FlushBlocks = ventoy_block_io_flush;
|
||||
|
||||
Status = gBS->InstallMultipleProtocolInterfaces(&gBlockData.Handle,
|
||||
&gEfiBlockIoProtocolGuid, &gBlockData.BlockIo,
|
||||
&gEfiDevicePathProtocolGuid, gBlockData.Path,
|
||||
NULL);
|
||||
|
||||
debug("Install protocol %r", Status);
|
||||
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = gBS->ConnectController(gBlockData.Handle, NULL, NULL, 1);
|
||||
debug("Connect controller %r", Status);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_load_image
|
||||
STATIC EFI_STATUS EFIAPI ventoy_load_image
|
||||
(
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *pDevicePath,
|
||||
@@ -745,6 +487,7 @@ 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;
|
||||
@@ -831,70 +574,6 @@ STATIC EFI_STATUS EFIAPI ventoy_load_isoefi_driver(IN EFI_HANDLE ImageHandle)
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
static int ventoy_update_image_location(ventoy_os_param *param)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
UINT8 chksum = 0;
|
||||
unsigned int i;
|
||||
unsigned int length;
|
||||
UINTN address = 0;
|
||||
void *buffer = NULL;
|
||||
ventoy_image_location *location = NULL;
|
||||
ventoy_image_disk_region *region = NULL;
|
||||
ventoy_img_chunk *chunk = g_chunk;
|
||||
|
||||
length = sizeof(ventoy_image_location) + (g_img_chunk_num - 1) * sizeof(ventoy_image_disk_region);
|
||||
|
||||
Status = gBS->AllocatePool(EfiRuntimeServicesData, length + 4096 * 2, &buffer);
|
||||
if (EFI_ERROR(Status) || NULL == buffer)
|
||||
{
|
||||
debug("Failed to allocate runtime pool %r\n", Status);
|
||||
return 1;
|
||||
}
|
||||
|
||||
address = (UINTN)buffer;
|
||||
|
||||
if (address % 4096)
|
||||
{
|
||||
address += 4096 - (address % 4096);
|
||||
}
|
||||
|
||||
param->chksum = 0;
|
||||
param->vtoy_img_location_addr = address;
|
||||
param->vtoy_img_location_len = length;
|
||||
|
||||
/* update check sum */
|
||||
for (i = 0; i < sizeof(ventoy_os_param); i++)
|
||||
{
|
||||
chksum += *((UINT8 *)param + i);
|
||||
}
|
||||
param->chksum = (chksum == 0) ? 0 : (UINT8)(0x100 - chksum);
|
||||
|
||||
location = (ventoy_image_location *)(unsigned long)(param->vtoy_img_location_addr);
|
||||
if (NULL == location)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
CopyMem(&location->guid, ¶m->guid, sizeof(ventoy_guid));
|
||||
location->image_sector_size = 2048;
|
||||
location->disk_sector_size = g_chain->disk_sector_size;
|
||||
location->region_count = g_img_chunk_num;
|
||||
|
||||
region = location->regions;
|
||||
|
||||
for (i = 0; i < g_img_chunk_num; i++)
|
||||
{
|
||||
region->image_sector_count = chunk->img_end_sector - chunk->img_start_sector + 1;
|
||||
region->image_start_sector = chunk->img_start_sector;
|
||||
region->disk_start_sector = chunk->disk_start_sector;
|
||||
region++;
|
||||
chunk++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
|
||||
{
|
||||
UINT32 i = 0;
|
||||
@@ -906,6 +585,7 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
ventoy_grub_param *pGrubParam = NULL;
|
||||
EFI_LOADED_IMAGE_PROTOCOL *pImageInfo = NULL;
|
||||
ventoy_chain_head *chain = NULL;
|
||||
|
||||
Status = gBS->HandleProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&pImageInfo);
|
||||
if (EFI_ERROR(Status))
|
||||
@@ -977,12 +657,15 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
|
||||
);
|
||||
|
||||
pPos = StrStr(pCmdLine, L"mem:");
|
||||
g_chain = (ventoy_chain_head *)StrHexToUintn(pPos + 4);
|
||||
chain = (ventoy_chain_head *)StrHexToUintn(pPos + 4);
|
||||
|
||||
pPos = StrStr(pPos, L"size:");
|
||||
size = StrDecimalToUintn(pPos + 5);
|
||||
|
||||
debug("memory addr:%p size:%lu", g_chain, size);
|
||||
debug("memory addr:%p size:%lu", chain, size);
|
||||
|
||||
g_chain = AllocatePool(size);
|
||||
CopyMem(g_chain, chain, size);
|
||||
|
||||
if (StrStr(pCmdLine, L"memdisk"))
|
||||
{
|
||||
@@ -998,6 +681,21 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
|
||||
g_virt_chunk = (ventoy_virt_chunk *)((char *)g_chain + g_chain->virt_chunk_offset);
|
||||
g_virt_chunk_num = g_chain->virt_chunk_num;
|
||||
|
||||
g_os_param_reserved = (UINT8 *)(g_chain->os_param.vtoy_reserved);
|
||||
|
||||
/* Workaround for Windows & ISO9660 */
|
||||
if (g_os_param_reserved[2] == ventoy_chain_windows && g_os_param_reserved[3] == 0)
|
||||
{
|
||||
g_fixup_iso9660_secover_enable = TRUE;
|
||||
}
|
||||
|
||||
if (g_os_param_reserved[2] == ventoy_chain_windows && g_os_param_reserved[4] != 1)
|
||||
{
|
||||
g_hook_keyboard = TRUE;
|
||||
}
|
||||
|
||||
debug("internal param: secover:%u keyboard:%u", g_fixup_iso9660_secover_enable, g_hook_keyboard);
|
||||
|
||||
for (i = 0; i < sizeof(ventoy_os_param); i++)
|
||||
{
|
||||
chksum += *((UINT8 *)(&(g_chain->os_param)) + i);
|
||||
@@ -1016,85 +714,85 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
|
||||
}
|
||||
}
|
||||
|
||||
g_fix_windows_1st_cdrom_issue = FALSE;
|
||||
if (ventoy_chain_windows == g_os_param_reserved[2] ||
|
||||
ventoy_chain_wim == g_os_param_reserved[2])
|
||||
{
|
||||
if (ventoy_is_cdrom_dp_exist())
|
||||
{
|
||||
debug("fixup the 1st cdrom influences when boot windows ...");
|
||||
g_fix_windows_1st_cdrom_issue = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
FreePool(pCmdLine);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_wrapper_file_open
|
||||
(
|
||||
EFI_FILE_HANDLE This,
|
||||
EFI_FILE_HANDLE *New,
|
||||
CHAR16 *Name,
|
||||
UINT64 Mode,
|
||||
UINT64 Attributes
|
||||
)
|
||||
EFI_STATUS EFIAPI ventoy_clean_env(VOID)
|
||||
{
|
||||
UINT32 i = 0;
|
||||
UINT32 j = 0;
|
||||
UINT64 Sectors = 0;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
CHAR8 TmpName[256];
|
||||
ventoy_virt_chunk *virt = NULL;
|
||||
FreePool(g_sector_flag);
|
||||
g_sector_flag_num = 0;
|
||||
|
||||
Status = g_original_fopen(This, New, Name, Mode, Attributes);
|
||||
if (EFI_ERROR(Status))
|
||||
if (gLoadIsoEfi && gBlockData.IsoDriverImage)
|
||||
{
|
||||
return Status;
|
||||
gBS->UnloadImage(gBlockData.IsoDriverImage);
|
||||
}
|
||||
|
||||
if (g_file_replace_list && g_file_replace_list->magic == GRUB_FILE_REPLACE_MAGIC &&
|
||||
g_file_replace_list->new_file_virtual_id < g_virt_chunk_num)
|
||||
gBS->DisconnectController(gBlockData.Handle, NULL, NULL);
|
||||
|
||||
gBS->UninstallMultipleProtocolInterfaces(gBlockData.Handle,
|
||||
&gEfiBlockIoProtocolGuid, &gBlockData.BlockIo,
|
||||
&gEfiDevicePathProtocolGuid, gBlockData.Path,
|
||||
NULL);
|
||||
|
||||
ventoy_delete_variable();
|
||||
|
||||
if (g_chain->os_param.vtoy_img_location_addr)
|
||||
{
|
||||
AsciiSPrint(TmpName, sizeof(TmpName), "%s", Name);
|
||||
for (j = 0; j < 4; j++)
|
||||
{
|
||||
if (0 == AsciiStrCmp(g_file_replace_list[i].old_file_name[j], TmpName))
|
||||
{
|
||||
g_original_fclose(*New);
|
||||
*New = &g_efi_file_replace.WrapperHandle;
|
||||
ventoy_wrapper_file_procotol(*New);
|
||||
|
||||
virt = g_virt_chunk + g_file_replace_list->new_file_virtual_id;
|
||||
|
||||
Sectors = (virt->mem_sector_end - virt->mem_sector_start) + (virt->remap_sector_end - virt->remap_sector_start);
|
||||
|
||||
g_efi_file_replace.BlockIoSectorStart = virt->mem_sector_start;
|
||||
g_efi_file_replace.FileSizeBytes = Sectors * 2048;
|
||||
|
||||
if (gDebugPrint)
|
||||
{
|
||||
debug("## ventoy_wrapper_file_open <%s> BlockStart:%lu Sectors:%lu Bytes:%lu", Name,
|
||||
g_efi_file_replace.BlockIoSectorStart, Sectors, Sectors * 2048);
|
||||
sleep(3);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
FreePool((VOID *)(UINTN)g_chain->os_param.vtoy_img_location_addr);
|
||||
}
|
||||
|
||||
return Status;
|
||||
FreePool(g_chain);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_wrapper_open_volume
|
||||
(
|
||||
IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
|
||||
OUT EFI_FILE_PROTOCOL **Root
|
||||
)
|
||||
STATIC EFI_STATUS ventoy_hook_start(VOID)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
|
||||
Status = g_original_open_volume(This, Root);
|
||||
if (!EFI_ERROR(Status))
|
||||
/* don't add debug print in this function */
|
||||
|
||||
if (g_fix_windows_1st_cdrom_issue)
|
||||
{
|
||||
g_original_fopen = (*Root)->Open;
|
||||
g_original_fclose = (*Root)->Close;
|
||||
(*Root)->Open = ventoy_wrapper_file_open;
|
||||
ventoy_hook_1st_cdrom_start();
|
||||
}
|
||||
|
||||
return Status;
|
||||
/* let this the last */
|
||||
if (g_hook_keyboard)
|
||||
{
|
||||
ventoy_hook_keyboard_start();
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
STATIC EFI_STATUS ventoy_hook_stop(VOID)
|
||||
{
|
||||
/* don't add debug print in this function */
|
||||
|
||||
if (g_fix_windows_1st_cdrom_issue)
|
||||
{
|
||||
ventoy_hook_1st_cdrom_stop();
|
||||
}
|
||||
|
||||
/* let this the last */
|
||||
if (g_hook_keyboard)
|
||||
{
|
||||
ventoy_hook_keyboard_stop();
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_boot(IN EFI_HANDLE ImageHandle)
|
||||
{
|
||||
@@ -1174,16 +872,20 @@ EFI_STATUS EFIAPI ventoy_boot(IN EFI_HANDLE ImageHandle)
|
||||
if (gDebugPrint)
|
||||
{
|
||||
gST->ConIn->Reset(gST->ConIn, FALSE);
|
||||
//ventoy_wrapper_system();
|
||||
}
|
||||
|
||||
if (g_file_replace_list && g_file_replace_list->magic == GRUB_FILE_REPLACE_MAGIC)
|
||||
{
|
||||
g_original_open_volume = pFile->OpenVolume;
|
||||
pFile->OpenVolume = ventoy_wrapper_open_volume;
|
||||
}
|
||||
|
||||
if (g_file_replace_list && g_file_replace_list->magic == GRUB_FILE_REPLACE_MAGIC)
|
||||
{
|
||||
ventoy_wrapper_push_openvolume(pFile->OpenVolume);
|
||||
pFile->OpenVolume = ventoy_wrapper_open_volume;
|
||||
}
|
||||
|
||||
ventoy_hook_start();
|
||||
/* can't add debug print here */
|
||||
//ventoy_wrapper_system();
|
||||
Status = gBS->StartImage(Image, NULL, NULL);
|
||||
ventoy_hook_stop();
|
||||
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
debug("Failed to start image %r", Status);
|
||||
@@ -1210,75 +912,6 @@ EFI_STATUS EFIAPI ventoy_boot(IN EFI_HANDLE ImageHandle)
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
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,
|
||||
&gEfiBlockIoProtocolGuid, &gBlockData.BlockIo,
|
||||
&gEfiDevicePathProtocolGuid, gBlockData.Path,
|
||||
NULL);
|
||||
|
||||
ventoy_delete_variable();
|
||||
|
||||
if (g_chain->os_param.vtoy_img_location_addr)
|
||||
{
|
||||
FreePool((VOID *)(UINTN)g_chain->os_param.vtoy_img_location_addr);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_ramdisk_boot(IN EFI_HANDLE ImageHandle)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_RAM_DISK_PROTOCOL *RamDisk = NULL;
|
||||
EFI_DEVICE_PATH_PROTOCOL *DevicePath = NULL;
|
||||
|
||||
debug("RamDisk Boot ...");
|
||||
|
||||
Status = gBS->LocateProtocol(&gEfiRamDiskProtocolGuid, NULL, (VOID **)&RamDisk);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
debug("Failed to locate ramdisk protocol %r", Status);
|
||||
return Status;
|
||||
}
|
||||
debug("Locate RamDisk Protocol %r ...", Status);
|
||||
|
||||
Status = RamDisk->Register((UINTN)g_chain, (UINT64)g_iso_buf_size, &gEfiVirtualCdGuid, NULL, &DevicePath);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
debug("Failed to register ramdisk %r", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
debug("Register RamDisk %r ...", Status);
|
||||
debug("RamDisk DevicePath:<%s> ...", ConvertDevicePathToText(DevicePath, FALSE, FALSE));
|
||||
|
||||
ventoy_debug_pause();
|
||||
|
||||
gBlockData.Path = DevicePath;
|
||||
gBlockData.DevicePathCompareLen = GetDevicePathSize(DevicePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);
|
||||
|
||||
Status = ventoy_boot(ImageHandle);
|
||||
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(300);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI VentoyEfiMain
|
||||
(
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
@@ -1286,6 +919,7 @@ EFI_STATUS EFIAPI VentoyEfiMain
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *Protocol;
|
||||
|
||||
g_sector_flag_num = 512; /* initial value */
|
||||
|
||||
@@ -1295,6 +929,12 @@ EFI_STATUS EFIAPI VentoyEfiMain
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Status = gBS->HandleProtocol(gST->ConsoleInHandle, &gEfiSimpleTextInputExProtocolGuid, (VOID **)&Protocol);
|
||||
if (EFI_SUCCESS == Status)
|
||||
{
|
||||
g_con_simple_input_ex = Protocol;
|
||||
}
|
||||
|
||||
gST->ConOut->ClearScreen(gST->ConOut);
|
||||
ventoy_clear_input();
|
||||
|
||||
@@ -1309,18 +949,12 @@ EFI_STATUS EFIAPI VentoyEfiMain
|
||||
|
||||
ventoy_install_blockio(ImageHandle, g_iso_buf_size);
|
||||
Status = ventoy_boot(ImageHandle);
|
||||
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(300);
|
||||
}
|
||||
|
||||
ventoy_del_ramdisk_param();
|
||||
|
||||
ventoy_delete_ramdisk_param();
|
||||
}
|
||||
else
|
||||
{
|
||||
ventoy_set_variable();
|
||||
ventoy_save_variable();
|
||||
ventoy_find_iso_disk(ImageHandle);
|
||||
|
||||
if (gLoadIsoEfi)
|
||||
@@ -1336,32 +970,20 @@ EFI_STATUS EFIAPI VentoyEfiMain
|
||||
ventoy_debug_pause();
|
||||
|
||||
Status = ventoy_boot(ImageHandle);
|
||||
if (EFI_NOT_FOUND == Status)
|
||||
{
|
||||
if (!gLoadIsoEfi)
|
||||
{
|
||||
gLoadIsoEfi = TRUE;
|
||||
ventoy_find_iso_disk_fs(ImageHandle);
|
||||
ventoy_load_isoefi_driver(ImageHandle);
|
||||
|
||||
Status = ventoy_boot(ImageHandle);
|
||||
}
|
||||
|
||||
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(60);
|
||||
}
|
||||
}
|
||||
|
||||
ventoy_clean_env();
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
@@ -25,6 +25,15 @@
|
||||
|
||||
#define VENTOY_GUID { 0x77772020, 0x2e77, 0x6576, { 0x6e, 0x74, 0x6f, 0x79, 0x2e, 0x6e, 0x65, 0x74 }}
|
||||
|
||||
typedef enum ventoy_chain_type
|
||||
{
|
||||
ventoy_chain_linux = 0, /* 0: linux */
|
||||
ventoy_chain_windows, /* 1: windows */
|
||||
ventoy_chain_wim, /* 2: wim */
|
||||
|
||||
ventoy_chain_max
|
||||
}ventoy_chain_type;
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
typedef struct ventoy_guid
|
||||
@@ -159,6 +168,8 @@ typedef struct ventoy_virt_chunk
|
||||
#define VTOY_BLOCK_DEVICE_PATH_GUID \
|
||||
{ 0x37b87ac6, 0xc180, 0x4583, { 0xa7, 0x05, 0x41, 0x4d, 0xa8, 0xf7, 0x7e, 0xd2 }}
|
||||
|
||||
#define ISO9660_EFI_DRIVER_PATH L"\\ventoy\\iso9660_x64.efi"
|
||||
|
||||
#define VTOY_BLOCK_DEVICE_PATH_NAME L"ventoy"
|
||||
|
||||
#if defined (MDE_CPU_IA32)
|
||||
@@ -202,7 +213,6 @@ typedef struct vtoy_block_data
|
||||
EFI_HANDLE IsoDriverImage;
|
||||
}vtoy_block_data;
|
||||
|
||||
#define ISO9660_EFI_DRIVER_PATH L"\\ventoy\\iso9660_x64.efi"
|
||||
|
||||
#define debug(expr, ...) if (gDebugPrint) VtoyDebug("[VTOY] "expr"\r\n", ##__VA_ARGS__)
|
||||
#define trace(expr, ...) VtoyDebug("[VTOY] "expr"\r\n", ##__VA_ARGS__)
|
||||
@@ -218,6 +228,7 @@ if (gDebugPrint) \
|
||||
}
|
||||
|
||||
typedef const char * (*grub_env_get_pf)(const char *name);
|
||||
typedef int (*grub_env_printf_pf)(const char *fmt, ...);
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
@@ -244,8 +255,8 @@ typedef struct ventoy_grub_param_file_replace
|
||||
typedef struct ventoy_grub_param
|
||||
{
|
||||
grub_env_get_pf grub_env_get;
|
||||
|
||||
ventoy_grub_param_file_replace file_replace;
|
||||
grub_env_printf_pf grub_env_printf;
|
||||
}ventoy_grub_param;
|
||||
|
||||
typedef struct ventoy_ram_disk
|
||||
@@ -254,6 +265,14 @@ typedef struct ventoy_ram_disk
|
||||
UINT64 DiskSize;
|
||||
}ventoy_ram_disk;
|
||||
|
||||
typedef struct ventoy_iso9660_override
|
||||
{
|
||||
UINT32 first_sector;
|
||||
UINT32 first_sector_be;
|
||||
UINT32 size;
|
||||
UINT32 size_be;
|
||||
}ventoy_iso9660_override;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
|
||||
@@ -273,6 +292,18 @@ typedef struct ventoy_system_wrapper
|
||||
|
||||
EFI_OPEN_PROTOCOL NewOpenProtocol;
|
||||
EFI_OPEN_PROTOCOL OriOpenProtocol;
|
||||
|
||||
EFI_LOCATE_HANDLE_BUFFER NewLocateHandleBuffer;
|
||||
EFI_LOCATE_HANDLE_BUFFER OriLocateHandleBuffer;
|
||||
|
||||
EFI_PROTOCOLS_PER_HANDLE NewProtocolsPerHandle;
|
||||
EFI_PROTOCOLS_PER_HANDLE OriProtocolsPerHandle;
|
||||
|
||||
EFI_LOCATE_HANDLE NewLocateHandle;
|
||||
EFI_LOCATE_HANDLE OriLocateHandle;
|
||||
|
||||
EFI_LOCATE_DEVICE_PATH NewLocateDevicePath;
|
||||
EFI_LOCATE_DEVICE_PATH OriLocateDevicePath;
|
||||
} ventoy_system_wrapper;
|
||||
|
||||
#define ventoy_wrapper(bs, wrapper, func, newfunc) \
|
||||
@@ -282,11 +313,9 @@ typedef struct ventoy_system_wrapper
|
||||
bs->func = wrapper.New##func;\
|
||||
}
|
||||
|
||||
extern ventoy_efi_file_replace g_efi_file_replace;
|
||||
extern BOOLEAN gDebugPrint;
|
||||
VOID EFIAPI VtoyDebug(IN CONST CHAR8 *Format, ...);
|
||||
EFI_STATUS EFIAPI ventoy_wrapper_system(VOID);
|
||||
EFI_STATUS EFIAPI ventoy_wrapper_file_procotol(EFI_FILE_PROTOCOL *File);
|
||||
EFI_STATUS EFIAPI ventoy_block_io_read
|
||||
(
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
@@ -296,5 +325,37 @@ EFI_STATUS EFIAPI ventoy_block_io_read
|
||||
OUT VOID *Buffer
|
||||
);
|
||||
|
||||
|
||||
extern ventoy_chain_head *g_chain;
|
||||
extern ventoy_img_chunk *g_chunk;
|
||||
extern UINT32 g_img_chunk_num;
|
||||
extern ventoy_override_chunk *g_override_chunk;
|
||||
extern UINT32 g_override_chunk_num;
|
||||
extern ventoy_virt_chunk *g_virt_chunk;
|
||||
extern UINT32 g_virt_chunk_num;
|
||||
extern vtoy_block_data gBlockData;
|
||||
extern ventoy_efi_file_replace g_efi_file_replace;
|
||||
extern ventoy_sector_flag *g_sector_flag;
|
||||
extern UINT32 g_sector_flag_num;
|
||||
extern BOOLEAN gMemdiskMode;
|
||||
extern UINTN g_iso_buf_size;
|
||||
extern ventoy_grub_param_file_replace *g_file_replace_list;
|
||||
extern BOOLEAN g_fixup_iso9660_secover_enable;
|
||||
extern EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *g_con_simple_input_ex;
|
||||
extern BOOLEAN g_fix_windows_1st_cdrom_issue;
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_wrapper_open_volume
|
||||
(
|
||||
IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
|
||||
OUT EFI_FILE_PROTOCOL **Root
|
||||
);
|
||||
EFI_STATUS EFIAPI ventoy_install_blockio(IN EFI_HANDLE ImageHandle, IN UINT64 ImgSize);
|
||||
EFI_STATUS EFIAPI ventoy_wrapper_push_openvolume(IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME OpenVolume);
|
||||
EFI_STATUS ventoy_hook_keyboard_start(VOID);
|
||||
EFI_STATUS ventoy_hook_keyboard_stop(VOID);
|
||||
BOOLEAN ventoy_is_cdrom_dp_exist(VOID);
|
||||
EFI_STATUS ventoy_hook_1st_cdrom_start(VOID);
|
||||
EFI_STATUS ventoy_hook_1st_cdrom_stop(VOID);
|
||||
|
||||
#endif
|
||||
|
@@ -29,6 +29,7 @@
|
||||
Ventoy.h
|
||||
Ventoy.c
|
||||
VentoyDebug.c
|
||||
VentoyProtocol.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
@@ -36,6 +36,10 @@
|
||||
#include <Protocol/SimpleFileSystem.h>
|
||||
#include <Ventoy.h>
|
||||
|
||||
#define PROCOTOL_SLEEP_MSECONDS 0
|
||||
|
||||
#define debug_sleep() if (PROCOTOL_SLEEP_MSECONDS) gBS->Stall(1000 * PROCOTOL_SLEEP_MSECONDS)
|
||||
|
||||
STATIC ventoy_system_wrapper g_system_wrapper;
|
||||
|
||||
static struct well_known_guid g_efi_well_known_guids[] =
|
||||
@@ -84,183 +88,6 @@ static const char * ventoy_get_guid_name(EFI_GUID *guid)
|
||||
return gEfiGuidName;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_fs_open(EFI_FILE_HANDLE This, EFI_FILE_HANDLE *New, CHAR16 *Name, UINT64 Mode, UINT64 Attributes)
|
||||
{
|
||||
(VOID)This;
|
||||
(VOID)New;
|
||||
(VOID)Name;
|
||||
(VOID)Mode;
|
||||
(VOID)Attributes;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_open_ex(EFI_FILE_HANDLE This, EFI_FILE_HANDLE *New, CHAR16 *Name, UINT64 Mode, UINT64 Attributes, EFI_FILE_IO_TOKEN *Token)
|
||||
{
|
||||
return ventoy_wrapper_fs_open(This, New, Name, Mode, Attributes);
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_delete(EFI_FILE_HANDLE This)
|
||||
{
|
||||
(VOID)This;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_set_info(EFI_FILE_HANDLE This, EFI_GUID *Type, UINTN Len, VOID *Data)
|
||||
{
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_flush(EFI_FILE_HANDLE This)
|
||||
{
|
||||
(VOID)This;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/* Ex version */
|
||||
EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_flush_ex(EFI_FILE_HANDLE This, EFI_FILE_IO_TOKEN *Token)
|
||||
{
|
||||
(VOID)This;
|
||||
(VOID)Token;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_write(EFI_FILE_HANDLE This, UINTN *Len, VOID *Data)
|
||||
{
|
||||
(VOID)This;
|
||||
(VOID)Len;
|
||||
(VOID)Data;
|
||||
|
||||
return EFI_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_write_ex(IN EFI_FILE_PROTOCOL *This, IN OUT EFI_FILE_IO_TOKEN *Token)
|
||||
{
|
||||
return ventoy_wrapper_file_write(This, &(Token->BufferSize), Token->Buffer);
|
||||
}
|
||||
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_close(EFI_FILE_HANDLE This)
|
||||
{
|
||||
(VOID)This;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_set_pos(EFI_FILE_HANDLE This, UINT64 Position)
|
||||
{
|
||||
(VOID)This;
|
||||
|
||||
g_efi_file_replace.CurPos = Position;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_get_pos(EFI_FILE_HANDLE This, UINT64 *Position)
|
||||
{
|
||||
(VOID)This;
|
||||
|
||||
*Position = g_efi_file_replace.CurPos;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_get_info(EFI_FILE_HANDLE This, EFI_GUID *Type, UINTN *Len, VOID *Data)
|
||||
{
|
||||
EFI_FILE_INFO *Info = (EFI_FILE_INFO *) Data;
|
||||
|
||||
debug("ventoy_wrapper_file_get_info ... %u", *Len);
|
||||
|
||||
if (!CompareGuid(Type, &gEfiFileInfoGuid))
|
||||
{
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (*Len == 0)
|
||||
{
|
||||
*Len = 384;
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
ZeroMem(Data, sizeof(EFI_FILE_INFO));
|
||||
|
||||
Info->Size = sizeof(EFI_FILE_INFO);
|
||||
Info->FileSize = g_efi_file_replace.FileSizeBytes;
|
||||
Info->PhysicalSize = g_efi_file_replace.FileSizeBytes;
|
||||
Info->Attribute = EFI_FILE_READ_ONLY;
|
||||
//Info->FileName = EFI_FILE_READ_ONLY;
|
||||
|
||||
*Len = Info->Size;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_read(EFI_FILE_HANDLE This, UINTN *Len, VOID *Data)
|
||||
{
|
||||
EFI_LBA Lba;
|
||||
UINTN ReadLen = *Len;
|
||||
|
||||
(VOID)This;
|
||||
|
||||
debug("ventoy_wrapper_file_read ... %u", *Len);
|
||||
|
||||
if (g_efi_file_replace.CurPos + ReadLen > g_efi_file_replace.FileSizeBytes)
|
||||
{
|
||||
ReadLen = g_efi_file_replace.FileSizeBytes - g_efi_file_replace.CurPos;
|
||||
}
|
||||
|
||||
Lba = g_efi_file_replace.CurPos / 2048 + g_efi_file_replace.BlockIoSectorStart;
|
||||
|
||||
ventoy_block_io_read(NULL, 0, Lba, ReadLen, Data);
|
||||
|
||||
*Len = ReadLen;
|
||||
|
||||
g_efi_file_replace.CurPos += ReadLen;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_read_ex(IN EFI_FILE_PROTOCOL *This, IN OUT EFI_FILE_IO_TOKEN *Token)
|
||||
{
|
||||
return ventoy_wrapper_file_read(This, &(Token->BufferSize), Token->Buffer);
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_wrapper_file_procotol(EFI_FILE_PROTOCOL *File)
|
||||
{
|
||||
File->Revision = EFI_FILE_PROTOCOL_REVISION2;
|
||||
File->Open = ventoy_wrapper_fs_open;
|
||||
File->Close = ventoy_wrapper_file_close;
|
||||
File->Delete = ventoy_wrapper_file_delete;
|
||||
File->Read = ventoy_wrapper_file_read;
|
||||
File->Write = ventoy_wrapper_file_write;
|
||||
File->GetPosition = ventoy_wrapper_file_get_pos;
|
||||
File->SetPosition = ventoy_wrapper_file_set_pos;
|
||||
File->GetInfo = ventoy_wrapper_file_get_info;
|
||||
File->SetInfo = ventoy_wrapper_file_set_info;
|
||||
File->Flush = ventoy_wrapper_file_flush;
|
||||
File->OpenEx = ventoy_wrapper_file_open_ex;
|
||||
File->ReadEx = ventoy_wrapper_file_read_ex;
|
||||
File->WriteEx = ventoy_wrapper_file_write_ex;
|
||||
File->FlushEx = ventoy_wrapper_file_flush_ex;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
STATIC EFI_STATUS EFIAPI ventoy_handle_protocol
|
||||
(
|
||||
IN EFI_HANDLE Handle,
|
||||
@@ -270,7 +97,7 @@ STATIC EFI_STATUS EFIAPI ventoy_handle_protocol
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
|
||||
debug("ventoy_handle_protocol:%a", ventoy_get_guid_name(Protocol));
|
||||
debug("ventoy_handle_protocol:%a", ventoy_get_guid_name(Protocol)); debug_sleep();
|
||||
Status = g_system_wrapper.OriHandleProtocol(Handle, Protocol, Interface);
|
||||
|
||||
if (CompareGuid(Protocol, &gEfiSimpleFileSystemProtocolGuid))
|
||||
@@ -280,7 +107,7 @@ STATIC EFI_STATUS EFIAPI ventoy_handle_protocol
|
||||
|
||||
pFile->OpenVolume(pFile, &FileProtocol);
|
||||
|
||||
debug("Handle FS Protocol: %p OpenVolume:%p, FileProtocol:%p, Open:%p",
|
||||
trace("Handle FS Protocol: %p OpenVolume:%p, FileProtocol:%p, Open:%p",
|
||||
pFile, pFile->OpenVolume, FileProtocol, FileProtocol->Open);
|
||||
|
||||
sleep(3);
|
||||
@@ -299,7 +126,7 @@ STATIC EFI_STATUS EFIAPI ventoy_open_protocol
|
||||
IN UINT32 Attributes
|
||||
)
|
||||
{
|
||||
debug("ventoy_open_protocol:%a", ventoy_get_guid_name(Protocol));
|
||||
debug("ventoy_open_protocol:<%p> %a", Handle, ventoy_get_guid_name(Protocol)); debug_sleep();
|
||||
return g_system_wrapper.OriOpenProtocol(Handle, Protocol, Interface, AgentHandle, ControllerHandle, Attributes);
|
||||
}
|
||||
|
||||
@@ -310,15 +137,91 @@ STATIC EFI_STATUS EFIAPI ventoy_locate_protocol
|
||||
OUT VOID **Interface
|
||||
)
|
||||
{
|
||||
debug("ventoy_locate_protocol:%a", ventoy_get_guid_name(Protocol));
|
||||
debug("ventoy_locate_protocol:%a", ventoy_get_guid_name(Protocol)); debug_sleep();
|
||||
return g_system_wrapper.OriLocateProtocol(Protocol, Registration, Interface);
|
||||
}
|
||||
|
||||
STATIC EFI_STATUS EFIAPI ventoy_locate_handle_buffer
|
||||
(
|
||||
IN EFI_LOCATE_SEARCH_TYPE SearchType,
|
||||
IN EFI_GUID *Protocol, OPTIONAL
|
||||
IN VOID *SearchKey, OPTIONAL
|
||||
IN OUT UINTN *NoHandles,
|
||||
OUT EFI_HANDLE **Buffer
|
||||
)
|
||||
{
|
||||
debug("ventoy_locate_handle_buffer:%a", ventoy_get_guid_name(Protocol)); debug_sleep();
|
||||
return g_system_wrapper.OriLocateHandleBuffer(SearchType, Protocol, SearchKey, NoHandles, Buffer);
|
||||
}
|
||||
|
||||
STATIC EFI_STATUS EFIAPI ventoy_protocol_per_handle
|
||||
(
|
||||
IN EFI_HANDLE Handle,
|
||||
OUT EFI_GUID ***ProtocolBuffer,
|
||||
OUT UINTN *ProtocolBufferCount
|
||||
)
|
||||
{
|
||||
debug("ventoy_protocol_per_handle:%p", Handle); debug_sleep();
|
||||
return g_system_wrapper.OriProtocolsPerHandle(Handle, ProtocolBuffer, ProtocolBufferCount);
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_locate_handle
|
||||
(
|
||||
IN EFI_LOCATE_SEARCH_TYPE SearchType,
|
||||
IN EFI_GUID *Protocol, OPTIONAL
|
||||
IN VOID *SearchKey, OPTIONAL
|
||||
IN OUT UINTN *BufferSize,
|
||||
OUT EFI_HANDLE *Buffer
|
||||
)
|
||||
{
|
||||
UINTN i;
|
||||
EFI_HANDLE Handle;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
|
||||
debug("ventoy_locate_handle: %d %a %p", SearchType, ventoy_get_guid_name(Protocol), SearchKey);
|
||||
Status = g_system_wrapper.OriLocateHandle(SearchType, Protocol, SearchKey, BufferSize, Buffer);
|
||||
debug("ventoy_locate_handle: %r Handle Count:%u", Status, *BufferSize/sizeof(EFI_HANDLE));
|
||||
|
||||
if (EFI_SUCCESS == Status)
|
||||
{
|
||||
for (i = 0; i < *BufferSize / sizeof(EFI_HANDLE); i++)
|
||||
{
|
||||
if (Buffer[i] == gBlockData.Handle)
|
||||
{
|
||||
Handle = Buffer[0];
|
||||
Buffer[0] = Buffer[i];
|
||||
Buffer[i] = Handle;
|
||||
debug("####### Handle at %u", i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
debug_sleep();
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
STATIC EFI_STATUS EFIAPI ventoy_locate_device_path
|
||||
(
|
||||
IN EFI_GUID *Protocol,
|
||||
IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,
|
||||
OUT EFI_HANDLE *Device
|
||||
)
|
||||
{
|
||||
debug("ventoy_locate_device_path:%a", ventoy_get_guid_name(Protocol)); debug_sleep();
|
||||
return g_system_wrapper.OriLocateDevicePath(Protocol, DevicePath, Device);
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_wrapper_system(VOID)
|
||||
{
|
||||
ventoy_wrapper(gBS, g_system_wrapper, LocateProtocol, ventoy_locate_protocol);
|
||||
ventoy_wrapper(gBS, g_system_wrapper, HandleProtocol, ventoy_handle_protocol);
|
||||
ventoy_wrapper(gBS, g_system_wrapper, OpenProtocol, ventoy_open_protocol);
|
||||
ventoy_wrapper(gBS, g_system_wrapper, LocateProtocol, ventoy_locate_protocol);
|
||||
ventoy_wrapper(gBS, g_system_wrapper, HandleProtocol, ventoy_handle_protocol);
|
||||
ventoy_wrapper(gBS, g_system_wrapper, OpenProtocol, ventoy_open_protocol);
|
||||
ventoy_wrapper(gBS, g_system_wrapper, LocateHandleBuffer, ventoy_locate_handle_buffer);
|
||||
ventoy_wrapper(gBS, g_system_wrapper, ProtocolsPerHandle, ventoy_protocol_per_handle);
|
||||
ventoy_wrapper(gBS, g_system_wrapper, LocateHandle, ventoy_locate_handle);
|
||||
ventoy_wrapper(gBS, g_system_wrapper, LocateDevicePath, ventoy_locate_device_path);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
@@ -0,0 +1,179 @@
|
||||
/******************************************************************************
|
||||
* Memhole.c
|
||||
*
|
||||
* Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Uefi.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/PrintLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DevicePathLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||
#include <Library/UefiApplicationEntryPoint.h>
|
||||
#include <Protocol/LoadedImage.h>
|
||||
#include <Guid/FileInfo.h>
|
||||
#include <Guid/FileSystemInfo.h>
|
||||
#include <Protocol/BlockIo.h>
|
||||
#include <Protocol/RamDisk.h>
|
||||
#include <Protocol/SimpleFileSystem.h>
|
||||
#include <VtoyUtil.h>
|
||||
|
||||
STATIC BOOLEAN IsMemContiguous
|
||||
(
|
||||
IN CONST EFI_MEMORY_DESCRIPTOR *Prev,
|
||||
IN CONST EFI_MEMORY_DESCRIPTOR *Curr,
|
||||
IN CONST EFI_MEMORY_DESCRIPTOR *Next
|
||||
)
|
||||
{
|
||||
UINTN Addr1 = 0;
|
||||
UINTN Addr2 = 0;
|
||||
|
||||
if (Prev == NULL || Curr == NULL || Next == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (Prev->Type == EfiBootServicesData &&
|
||||
Curr->Type == EfiConventionalMemory &&
|
||||
Next->Type == EfiBootServicesData)
|
||||
{
|
||||
Addr1 = Prev->PhysicalStart + MultU64x64(SIZE_4KB, Prev->NumberOfPages);
|
||||
Addr2 = Curr->PhysicalStart + MultU64x64(SIZE_4KB, Curr->NumberOfPages);
|
||||
|
||||
if (Addr1 == Curr->PhysicalStart && Addr2 == Next->PhysicalStart)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
STATIC EFI_MEMORY_DESCRIPTOR* GetMemDesc
|
||||
(
|
||||
OUT UINTN *pSize,
|
||||
OUT UINTN *pItemSize,
|
||||
OUT UINTN *pDescCount
|
||||
)
|
||||
{
|
||||
UINTN Size = 0;
|
||||
UINTN MapKey = 0;
|
||||
UINTN ItemSize = 0;
|
||||
UINTN DescCount = 0;
|
||||
UINT32 Version = 0;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_MEMORY_DESCRIPTOR *pDesc = NULL;
|
||||
EFI_MEMORY_DESCRIPTOR *Curr = NULL;
|
||||
|
||||
Status = gBS->GetMemoryMap(&Size, pDesc, &MapKey, &ItemSize, &Version);
|
||||
if (EFI_BUFFER_TOO_SMALL != Status)
|
||||
{
|
||||
debug("GetMemoryMap: %r", Status);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Size += SIZE_1KB;
|
||||
pDesc = AllocatePool(Size);
|
||||
if (!pDesc)
|
||||
{
|
||||
debug("AllocatePool: %lu failed", Size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ZeroMem(pDesc, Size);
|
||||
|
||||
Status = gBS->GetMemoryMap(&Size, pDesc, &MapKey, &ItemSize, &Version);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
debug("GetMemoryMap: %r", Status);
|
||||
FreePool(pDesc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Curr = pDesc;
|
||||
while (Curr && Curr < (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)pDesc + Size))
|
||||
{
|
||||
DescCount++;
|
||||
Curr = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)Curr + ItemSize);
|
||||
}
|
||||
|
||||
*pSize = Size;
|
||||
*pItemSize = ItemSize;
|
||||
*pDescCount = DescCount;
|
||||
|
||||
debug("GetMemoryMap: ItemSize:%lu Count:%lu", ItemSize, DescCount);
|
||||
|
||||
return pDesc;
|
||||
}
|
||||
|
||||
EFI_STATUS FixWindowsMemhole(IN EFI_HANDLE ImageHandle, IN CONST CHAR16 *CmdLine)
|
||||
{
|
||||
UINTN Size = 0;
|
||||
UINTN ItemSize = 0;
|
||||
UINTN DescCount = 0;
|
||||
UINTN TotalMem = 0;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_PHYSICAL_ADDRESS AllocAddr = 0;
|
||||
EFI_MEMORY_DESCRIPTOR *pDescs = NULL;
|
||||
EFI_MEMORY_DESCRIPTOR *Prev = NULL;
|
||||
EFI_MEMORY_DESCRIPTOR *Next = NULL;
|
||||
EFI_MEMORY_DESCRIPTOR *Curr = NULL;
|
||||
|
||||
(VOID)ImageHandle;
|
||||
(VOID)CmdLine;
|
||||
|
||||
pDescs = GetMemDesc(&Size, &ItemSize, &DescCount);
|
||||
if (!pDescs)
|
||||
{
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (DescCount < 500)
|
||||
{
|
||||
FreePool(pDescs);
|
||||
Printf("There is no need to fixup (%lu)\n", DescCount);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
Curr = pDescs;
|
||||
while ((UINT8 *)Curr < (UINT8 *)pDescs + Size)
|
||||
{
|
||||
Next = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)Curr + ItemSize);
|
||||
|
||||
if (IsMemContiguous(Prev, Curr, Next))
|
||||
{
|
||||
AllocAddr = Curr->PhysicalStart;
|
||||
Status = gBS->AllocatePages(AllocateAddress, EfiBootServicesData, Curr->NumberOfPages, &AllocAddr);
|
||||
if (EFI_SUCCESS == Status)
|
||||
{
|
||||
TotalMem += MultU64x64(SIZE_4KB, Curr->NumberOfPages);
|
||||
}
|
||||
}
|
||||
|
||||
Prev = Curr;
|
||||
Curr = Next;
|
||||
}
|
||||
|
||||
Printf("Fixup Windows mmap issue OK (%lu)\n", TotalMem);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
@@ -0,0 +1,135 @@
|
||||
/******************************************************************************
|
||||
* VtoyUtil.c
|
||||
*
|
||||
* Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Uefi.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/PrintLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DevicePathLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||
#include <Library/UefiApplicationEntryPoint.h>
|
||||
#include <Protocol/LoadedImage.h>
|
||||
#include <Guid/FileInfo.h>
|
||||
#include <Guid/FileSystemInfo.h>
|
||||
#include <Protocol/BlockIo.h>
|
||||
#include <Protocol/RamDisk.h>
|
||||
#include <Protocol/SimpleFileSystem.h>
|
||||
#include <VtoyUtil.h>
|
||||
|
||||
BOOLEAN gVtoyDebugPrint = FALSE;
|
||||
STATIC CONST CHAR16 *gCurFeature= NULL;
|
||||
STATIC CHAR16 *gCmdLine = NULL;
|
||||
STATIC grub_env_printf_pf g_env_printf = NULL;
|
||||
|
||||
STATIC VtoyUtilFeature gFeatureList[] =
|
||||
{
|
||||
{ L"fix_windows_mmap", FixWindowsMemhole },
|
||||
};
|
||||
|
||||
VOID EFIAPI VtoyUtilDebug(IN CONST CHAR8 *Format, ...)
|
||||
{
|
||||
VA_LIST Marker;
|
||||
CHAR8 Buffer[512];
|
||||
|
||||
VA_START (Marker, Format);
|
||||
AsciiVSPrint(Buffer, sizeof(Buffer), Format, Marker);
|
||||
VA_END (Marker);
|
||||
|
||||
if (g_env_printf)
|
||||
{
|
||||
g_env_printf("%s", Buffer);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC EFI_STATUS ParseCmdline(IN EFI_HANDLE ImageHandle)
|
||||
{
|
||||
CHAR16 *pPos = NULL;
|
||||
CHAR16 *pCmdLine = NULL;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
ventoy_grub_param *pGrubParam = NULL;
|
||||
EFI_LOADED_IMAGE_PROTOCOL *pImageInfo = NULL;
|
||||
|
||||
Status = gBS->HandleProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&pImageInfo);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
pCmdLine = (CHAR16 *)AllocatePool(pImageInfo->LoadOptionsSize + 4);
|
||||
SetMem(pCmdLine, pImageInfo->LoadOptionsSize + 4, 0);
|
||||
CopyMem(pCmdLine, pImageInfo->LoadOptions, pImageInfo->LoadOptionsSize);
|
||||
|
||||
if (StrStr(pCmdLine, L"debug"))
|
||||
{
|
||||
gVtoyDebugPrint = TRUE;
|
||||
}
|
||||
|
||||
pPos = StrStr(pCmdLine, L"env_param=");
|
||||
if (!pPos)
|
||||
{
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
pGrubParam = (ventoy_grub_param *)StrHexToUintn(pPos + StrLen(L"env_param="));
|
||||
g_env_printf = pGrubParam->grub_env_printf;
|
||||
|
||||
pPos = StrStr(pCmdLine, L"feature=");
|
||||
if (!pPos)
|
||||
{
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
gCurFeature = pPos + StrLen(L"feature=");
|
||||
|
||||
gCmdLine = pCmdLine;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI VtoyUtilEfiMain
|
||||
(
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
UINTN i;
|
||||
UINTN Len;
|
||||
|
||||
ParseCmdline(ImageHandle);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(gFeatureList); i++)
|
||||
{
|
||||
Len = StrLen(gFeatureList[i].Cmd);
|
||||
if (StrnCmp(gFeatureList[i].Cmd, gCurFeature, Len) == 0)
|
||||
{
|
||||
debug("Find main proc <%s>", gFeatureList[i].Cmd);
|
||||
gFeatureList[i].MainProc(ImageHandle, gCurFeature + Len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FreePool(gCmdLine);
|
||||
gCmdLine = NULL;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
@@ -0,0 +1,61 @@
|
||||
/******************************************************************************
|
||||
* VtoyUtil.h
|
||||
*
|
||||
* Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __VTOYUTIL_H__
|
||||
#define __VTOYUTIL_H__
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
typedef EFI_STATUS (*VTOY_UTIL_PROC_PF)(IN EFI_HANDLE ImageHandle, IN CONST CHAR16 *CmdLine);
|
||||
typedef const char * (*grub_env_get_pf)(const char *name);
|
||||
typedef int (*grub_env_printf_pf)(const char *fmt, ...);
|
||||
|
||||
typedef struct ventoy_grub_param_file_replace
|
||||
{
|
||||
UINT32 magic;
|
||||
char old_file_name[4][256];
|
||||
UINT32 old_file_cnt;
|
||||
UINT32 new_file_virtual_id;
|
||||
}ventoy_grub_param_file_replace;
|
||||
|
||||
typedef struct ventoy_grub_param
|
||||
{
|
||||
grub_env_get_pf grub_env_get;
|
||||
ventoy_grub_param_file_replace file_replace;
|
||||
grub_env_printf_pf grub_env_printf;
|
||||
}ventoy_grub_param;
|
||||
#pragma pack()
|
||||
|
||||
|
||||
typedef struct VtoyUtilFeature
|
||||
{
|
||||
CONST CHAR16 *Cmd;
|
||||
VTOY_UTIL_PROC_PF MainProc;
|
||||
}VtoyUtilFeature;
|
||||
|
||||
extern BOOLEAN gVtoyDebugPrint;
|
||||
VOID EFIAPI VtoyUtilDebug(IN CONST CHAR8 *Format, ...);
|
||||
#define debug(expr, ...) if (gVtoyDebugPrint) VtoyUtilDebug("[VTOY] "expr"\n", ##__VA_ARGS__)
|
||||
#define Printf VtoyUtilDebug
|
||||
|
||||
EFI_STATUS FixWindowsMemhole(IN EFI_HANDLE ImageHandle, IN CONST CHAR16 *CmdLine);
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,80 @@
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = VtoyUtil
|
||||
FILE_GUID = a43466a0-68c6-469d-ba4b-678bbe90bc47
|
||||
MODULE_TYPE = UEFI_APPLICATION
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = VtoyUtilEfiMain
|
||||
|
||||
|
||||
[Sources]
|
||||
VtoyUtil.h
|
||||
VtoyUtil.c
|
||||
Memhole.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
ShellPkg/ShellPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
UefiApplicationEntryPoint
|
||||
UefiLib
|
||||
DebugLib
|
||||
|
||||
[Guids]
|
||||
gShellVariableGuid
|
||||
gEfiVirtualCdGuid
|
||||
gEfiFileInfoGuid
|
||||
|
||||
[Protocols]
|
||||
gEfiLoadedImageProtocolGuid
|
||||
gEfiBlockIoProtocolGuid
|
||||
gEfiDevicePathProtocolGuid
|
||||
gEfiSimpleFileSystemProtocolGuid
|
||||
gEfiRamDiskProtocolGuid
|
||||
gEfiAbsolutePointerProtocolGuid
|
||||
gEfiAcpiTableProtocolGuid
|
||||
gEfiBlockIo2ProtocolGuid
|
||||
gEfiBusSpecificDriverOverrideProtocolGuid
|
||||
gEfiComponentNameProtocolGuid
|
||||
gEfiComponentName2ProtocolGuid
|
||||
gEfiDriverBindingProtocolGuid
|
||||
gEfiDiskIoProtocolGuid
|
||||
gEfiDiskIo2ProtocolGuid
|
||||
gEfiGraphicsOutputProtocolGuid
|
||||
gEfiHiiConfigAccessProtocolGuid
|
||||
gEfiHiiFontProtocolGuid
|
||||
gEfiLoadFileProtocolGuid
|
||||
gEfiLoadFile2ProtocolGuid
|
||||
gEfiLoadedImageProtocolGuid
|
||||
gEfiLoadedImageDevicePathProtocolGuid
|
||||
gEfiPciIoProtocolGuid
|
||||
gEfiSerialIoProtocolGuid
|
||||
gEfiSimpleTextInProtocolGuid
|
||||
gEfiSimpleTextInputExProtocolGuid
|
||||
gEfiSimpleTextOutProtocolGuid
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -204,6 +204,7 @@
|
||||
|
||||
[Components]
|
||||
MdeModulePkg/Application/Ventoy/Ventoy.inf
|
||||
MdeModulePkg/Application/VtoyUtil/VtoyUtil.inf
|
||||
MdeModulePkg/Application/HelloWorld/HelloWorld.inf
|
||||
MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.inf
|
||||
MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf
|
1141
EDK2/efiffs/mod/grub/grub-core/fs/iso9660.c
Normal file
794
EDK2/efiffs/mod/src/file.c
Normal file
@@ -0,0 +1,794 @@
|
||||
/* file.c - SimpleFileIo Interface */
|
||||
/*
|
||||
* Copyright © 2014-2017 Pete Batard <pete@akeo.ie>
|
||||
* Based on iPXE's efi_driver.c and efi_file.c:
|
||||
* Copyright © 2011,2013 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 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 "driver.h"
|
||||
|
||||
/**
|
||||
* Get EFI file name (for debugging)
|
||||
*
|
||||
* @v file EFI file
|
||||
* @ret Name Name
|
||||
*/
|
||||
static const CHAR16 *
|
||||
FileName(EFI_GRUB_FILE *File)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
static CHAR16 Path[MAX_PATH];
|
||||
|
||||
Status = Utf8ToUtf16NoAlloc(File->path, Path, sizeof(Path));
|
||||
if (EFI_ERROR(Status)) {
|
||||
PrintStatusError(Status, L"Could not convert filename to UTF16");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return Path;
|
||||
}
|
||||
|
||||
/* Simple hook to populate the timestamp and directory flag when opening a file */
|
||||
static INT32
|
||||
InfoHook(const CHAR8 *name, const GRUB_DIRHOOK_INFO *Info, VOID *Data)
|
||||
{
|
||||
EFI_GRUB_FILE *File = (EFI_GRUB_FILE *) Data;
|
||||
|
||||
/* Look for a specific file */
|
||||
if (strcmpa(name, File->basename) != 0)
|
||||
return 0;
|
||||
|
||||
File->IsDir = (BOOLEAN) (Info->Dir);
|
||||
if (Info->MtimeSet)
|
||||
File->Mtime = Info->Mtime;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open file
|
||||
*
|
||||
* @v This File handle
|
||||
* @ret new New file handle
|
||||
* @v Name File name
|
||||
* @v Mode File mode
|
||||
* @v Attributes File attributes (for newly-created files)
|
||||
* @ret Status EFI status code
|
||||
*/
|
||||
static EFI_STATUS EFIAPI
|
||||
FileOpen(EFI_FILE_HANDLE This, EFI_FILE_HANDLE *New,
|
||||
CHAR16 *Name, UINT64 Mode, UINT64 Attributes)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
|
||||
EFI_GRUB_FILE *NewFile;
|
||||
|
||||
// TODO: Use dynamic buffers?
|
||||
char path[MAX_PATH], clean_path[MAX_PATH], *dirname;
|
||||
INTN i, len;
|
||||
BOOLEAN AbsolutePath = (*Name == L'\\');
|
||||
|
||||
PrintInfo(L"Open(" PERCENT_P L"%s, \"%s\")\n", (UINTN) This,
|
||||
IS_ROOT(File)?L" <ROOT>":L"", Name);
|
||||
|
||||
/* Fail unless opening read-only */
|
||||
if (Mode != EFI_FILE_MODE_READ) {
|
||||
PrintWarning(L"File '%s' can only be opened in read-only mode\n", Name);
|
||||
return EFI_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
/* Additional failures */
|
||||
if ((StrCmp(Name, L"..") == 0) && IS_ROOT(File)) {
|
||||
PrintInfo(L"Trying to open <ROOT>'s parent\n");
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
/* See if we're trying to reopen current (which the EFI Shell insists on doing) */
|
||||
if ((*Name == 0) || (StrCmp(Name, L".") == 0)) {
|
||||
PrintInfo(L" Reopening %s\n", IS_ROOT(File)?L"<ROOT>":FileName(File));
|
||||
File->RefCount++;
|
||||
*New = This;
|
||||
PrintInfo(L" RET: " PERCENT_P L"\n", (UINTN) *New);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/* If we have an absolute path, don't bother completing with the parent */
|
||||
if (AbsolutePath) {
|
||||
len = 0;
|
||||
} else {
|
||||
strcpya(path, File->path);
|
||||
len = strlena(path);
|
||||
/* Add delimiter if needed */
|
||||
if ((len == 0) || (path[len-1] != '/'))
|
||||
path[len++] = '/';
|
||||
}
|
||||
|
||||
/* Copy the rest of the path (converted to UTF-8) */
|
||||
Status = Utf16ToUtf8NoAlloc(Name, &path[len], sizeof(path) - len);
|
||||
if (EFI_ERROR(Status)) {
|
||||
PrintStatusError(Status, L"Could not convert path to UTF-8");
|
||||
return Status;
|
||||
}
|
||||
/* Convert the delimiters */
|
||||
for (i = strlena(path) - 1 ; i >= len; i--) {
|
||||
if (path[i] == '\\')
|
||||
path[i] = '/';
|
||||
}
|
||||
|
||||
/* We only want to handle with absolute paths */
|
||||
clean_path[0] = '/';
|
||||
/* Find out if we're dealing with root by removing the junk */
|
||||
CopyPathRelative(&clean_path[1], path, MAX_PATH - 1);
|
||||
if (clean_path[1] == 0) {
|
||||
/* We're dealing with the root */
|
||||
PrintInfo(L" Reopening <ROOT>\n");
|
||||
*New = &File->FileSystem->RootFile->EfiFile;
|
||||
/* Must make sure that DirIndex is reset too (NB: no concurrent access!) */
|
||||
File->FileSystem->RootFile->DirIndex = 0;
|
||||
PrintInfo(L" RET: " PERCENT_P L"\n", (UINTN) *New);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
// TODO: eventually we should seek for already opened files and increase RefCount
|
||||
/* Allocate and initialise an instance of a file */
|
||||
Status = GrubCreateFile(&NewFile, File->FileSystem);
|
||||
if (EFI_ERROR(Status)) {
|
||||
PrintStatusError(Status, L"Could not instantiate file");
|
||||
return Status;
|
||||
}
|
||||
|
||||
NewFile->path = AllocatePool(strlena(clean_path)+1);
|
||||
if (NewFile->path == NULL) {
|
||||
GrubDestroyFile(NewFile);
|
||||
PrintError(L"Could not instantiate path\n");
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
strcpya(NewFile->path, clean_path);
|
||||
|
||||
/* Isolate the basename and dirname */
|
||||
for (i = strlena(clean_path) - 1; i >= 0; i--) {
|
||||
if (clean_path[i] == '/') {
|
||||
clean_path[i] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
dirname = (i <= 0) ? "/" : clean_path;
|
||||
NewFile->basename = &NewFile->path[i+1];
|
||||
|
||||
/* Find if we're working with a directory and fill the grub timestamp */
|
||||
Status = GrubDir(NewFile, dirname, InfoHook, (VOID *) NewFile);
|
||||
if (EFI_ERROR(Status)) {
|
||||
if (Status != EFI_NOT_FOUND)
|
||||
PrintStatusError(Status, L"Could not get file attributes for '%s'", Name);
|
||||
FreePool(NewFile->path);
|
||||
GrubDestroyFile(NewFile);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Finally we can call on GRUB open() if it's a regular file */
|
||||
if (!NewFile->IsDir) {
|
||||
Status = GrubOpen(NewFile);
|
||||
if (EFI_ERROR(Status)) {
|
||||
if (Status != EFI_NOT_FOUND)
|
||||
PrintStatusError(Status, L"Could not open file '%s'", Name);
|
||||
FreePool(NewFile->path);
|
||||
GrubDestroyFile(NewFile);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
NewFile->RefCount++;
|
||||
*New = &NewFile->EfiFile;
|
||||
|
||||
PrintInfo(L" RET: " PERCENT_P L"\n", (UINTN) *New);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/* Ex version */
|
||||
static EFI_STATUS EFIAPI
|
||||
FileOpenEx(EFI_FILE_HANDLE This, EFI_FILE_HANDLE *New, CHAR16 *Name,
|
||||
UINT64 Mode, UINT64 Attributes, EFI_FILE_IO_TOKEN *Token)
|
||||
{
|
||||
return FileOpen(This, New, Name, Mode, Attributes);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Close file
|
||||
*
|
||||
* @v This File handle
|
||||
* @ret Status EFI status code
|
||||
*/
|
||||
static EFI_STATUS EFIAPI
|
||||
FileClose(EFI_FILE_HANDLE This)
|
||||
{
|
||||
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
|
||||
|
||||
PrintInfo(L"Close(" PERCENT_P L"|'%s') %s\n", (UINTN) This, FileName(File),
|
||||
IS_ROOT(File)?L"<ROOT>":L"");
|
||||
|
||||
/* Nothing to do it this is the root */
|
||||
if (IS_ROOT(File))
|
||||
return EFI_SUCCESS;
|
||||
|
||||
if (--File->RefCount == 0) {
|
||||
/* Close the file if it's a regular one */
|
||||
if (!File->IsDir)
|
||||
GrubClose(File);
|
||||
/* NB: basename points into File->path and does not need to be freed */
|
||||
if (File->path != NULL)
|
||||
FreePool(File->path);
|
||||
GrubDestroyFile(File);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close and delete file
|
||||
*
|
||||
* @v This File handle
|
||||
* @ret Status EFI status code
|
||||
*/
|
||||
static EFI_STATUS EFIAPI
|
||||
FileDelete(EFI_FILE_HANDLE This)
|
||||
{
|
||||
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
|
||||
|
||||
PrintError(L"Cannot delete '%s'\n", FileName(File));
|
||||
|
||||
/* Close file */
|
||||
FileClose(This);
|
||||
|
||||
/* Warn of failure to delete */
|
||||
return EFI_WARN_DELETE_FAILURE;
|
||||
}
|
||||
|
||||
/* GRUB uses a callback for each directory entry, whereas EFI uses repeated
|
||||
* firmware generated calls to FileReadDir() to get the info for each entry,
|
||||
* so we have to reconcile the twos. For now, we'll re-issue a call to GRUB
|
||||
* dir(), and run through all the entries (to find the one we
|
||||
* are interested in) multiple times. Maybe later we'll try to optimize this
|
||||
* by building a one-off chained list of entries that we can parse...
|
||||
*/
|
||||
static INT32
|
||||
DirHook(const CHAR8 *name, const GRUB_DIRHOOK_INFO *DirInfo, VOID *Data)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_FILE_INFO *Info = (EFI_FILE_INFO *) Data;
|
||||
INT64 *Index = (INT64 *) &Info->FileSize;
|
||||
CHAR8 *filename = (CHAR8 *) (UINTN) Info->PhysicalSize;
|
||||
EFI_TIME Time = { 1970, 01, 01, 00, 00, 00, 0, 0, 0, 0, 0};
|
||||
|
||||
// Eliminate '.' or '..'
|
||||
if ((name[0] == '.') && ((name[1] == 0) || ((name[1] == '.') && (name[2] == 0))))
|
||||
return 0;
|
||||
|
||||
/* Ignore any entry that doesn't match our index */
|
||||
if ((*Index)-- != 0)
|
||||
return 0;
|
||||
|
||||
strcpya(filename, name);
|
||||
|
||||
Status = Utf8ToUtf16NoAlloc(filename, Info->FileName, (INTN)(Info->Size - sizeof(EFI_FILE_INFO)));
|
||||
if (EFI_ERROR(Status)) {
|
||||
if (Status != EFI_BUFFER_TOO_SMALL)
|
||||
PrintStatusError(Status, L"Could not convert directory entry to UTF-8");
|
||||
return (INT32) Status;
|
||||
}
|
||||
/* The Info struct size already accounts for the extra NUL */
|
||||
Info->Size = sizeof(*Info) + StrLen(Info->FileName) * sizeof(CHAR16);
|
||||
|
||||
// Oh, and of course GRUB uses a 32 bit signed mtime value (seriously, wtf guys?!?)
|
||||
if (DirInfo->MtimeSet)
|
||||
GrubTimeToEfiTime(DirInfo->Mtime, &Time);
|
||||
CopyMem(&Info->CreateTime, &Time, sizeof(Time));
|
||||
CopyMem(&Info->LastAccessTime, &Time, sizeof(Time));
|
||||
CopyMem(&Info->ModificationTime, &Time, sizeof(Time));
|
||||
|
||||
Info->Attribute = EFI_FILE_READ_ONLY;
|
||||
if (DirInfo->Dir)
|
||||
Info->Attribute |= EFI_FILE_DIRECTORY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read directory entry
|
||||
*
|
||||
* @v file EFI file
|
||||
* @v Len Length to read
|
||||
* @v Data Data buffer
|
||||
* @ret Status EFI status code
|
||||
*/
|
||||
static EFI_STATUS
|
||||
FileReadDir(EFI_GRUB_FILE *File, UINTN *Len, VOID *Data)
|
||||
{
|
||||
EFI_FILE_INFO *Info = (EFI_FILE_INFO *) Data;
|
||||
EFI_STATUS Status;
|
||||
/* We temporarily repurpose the FileSize as a *signed* entry index */
|
||||
INT64 *Index = (INT64 *) &Info->FileSize;
|
||||
/* And PhysicalSize as a pointer to our filename */
|
||||
CHAR8 **basename = (CHAR8 **) &Info->PhysicalSize;
|
||||
CHAR8 path[MAX_PATH];
|
||||
EFI_GRUB_FILE *TmpFile = NULL;
|
||||
INTN len;
|
||||
|
||||
/* Unless we can fit our maximum size, forget it */
|
||||
if (*Len < sizeof(EFI_FILE_INFO)) {
|
||||
*Len = MINIMUM_INFO_LENGTH;
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
/* Populate our Info template */
|
||||
ZeroMem(Data, *Len);
|
||||
Info->Size = *Len;
|
||||
*Index = File->DirIndex;
|
||||
strcpya(path, File->path);
|
||||
len = strlena(path);
|
||||
if (path[len-1] != '/')
|
||||
path[len++] = '/';
|
||||
*basename = &path[len];
|
||||
|
||||
/* Invoke GRUB's directory listing */
|
||||
Status = GrubDir(File, File->path, DirHook, Data);
|
||||
if (*Index >= 0) {
|
||||
/* No more entries */
|
||||
*Len = 0;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
if (EFI_ERROR(Status)) {
|
||||
if (Status == EFI_BUFFER_TOO_SMALL) {
|
||||
*Len = MINIMUM_INFO_LENGTH;
|
||||
} else {
|
||||
PrintStatusError(Status, L"Directory listing failed");
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Our Index/FileSize must be reset */
|
||||
Info->FileSize = 0;
|
||||
Info->PhysicalSize = 0;
|
||||
|
||||
/* For regular files, we still need to fill the size */
|
||||
if (!(Info->Attribute & EFI_FILE_DIRECTORY)) {
|
||||
/* Open the file and read its size */
|
||||
Status = GrubCreateFile(&TmpFile, File->FileSystem);
|
||||
if (EFI_ERROR(Status)) {
|
||||
PrintStatusError(Status, L"Unable to create temporary file");
|
||||
return Status;
|
||||
}
|
||||
TmpFile->path = path;
|
||||
|
||||
Status = GrubOpen(TmpFile);
|
||||
if (EFI_ERROR(Status)) {
|
||||
// TODO: EFI_NO_MAPPING is returned for links...
|
||||
PrintStatusError(Status, L"Unable to obtain the size of '%s'", Info->FileName);
|
||||
/* Non fatal error */
|
||||
} else {
|
||||
Info->FileSize = GrubGetFileSize(TmpFile);
|
||||
Info->PhysicalSize = GrubGetFileSize(TmpFile);
|
||||
GrubClose(TmpFile);
|
||||
}
|
||||
GrubDestroyFile(TmpFile);
|
||||
}
|
||||
|
||||
*Len = (UINTN) Info->Size;
|
||||
/* Advance to the next entry */
|
||||
File->DirIndex++;
|
||||
|
||||
// PrintInfo(L" Entry[%d]: '%s' %s\n", File->DirIndex-1, Info->FileName,
|
||||
// (Info->Attribute&EFI_FILE_DIRECTORY)?L"<DIR>":L"");
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read from file
|
||||
*
|
||||
* @v This File handle
|
||||
* @v Len Length to read
|
||||
* @v Data Data buffer
|
||||
* @ret Status EFI status code
|
||||
*/
|
||||
static EFI_STATUS EFIAPI
|
||||
FileRead(EFI_FILE_HANDLE This, UINTN *Len, VOID *Data)
|
||||
{
|
||||
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
|
||||
|
||||
PrintInfo(L"Read(" PERCENT_P L"|'%s', %d) %s\n", (UINTN) This, FileName(File),
|
||||
*Len, File->IsDir?L"<DIR>":L"");
|
||||
|
||||
/* If this is a directory, then fetch the directory entries */
|
||||
if (File->IsDir)
|
||||
return FileReadDir(File, Len, Data);
|
||||
|
||||
return GrubRead(File, Data, Len);
|
||||
}
|
||||
|
||||
/* Ex version */
|
||||
static EFI_STATUS EFIAPI
|
||||
FileReadEx(IN EFI_FILE_PROTOCOL *This, IN OUT EFI_FILE_IO_TOKEN *Token)
|
||||
{
|
||||
return FileRead(This, &(Token->BufferSize), Token->Buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write to file
|
||||
*
|
||||
* @v This File handle
|
||||
* @v Len Length to write
|
||||
* @v Data Data buffer
|
||||
* @ret Status EFI status code
|
||||
*/
|
||||
static EFI_STATUS EFIAPI
|
||||
FileWrite(EFI_FILE_HANDLE This, UINTN *Len, VOID *Data)
|
||||
{
|
||||
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
|
||||
|
||||
PrintError(L"Cannot write to '%s'\n", FileName(File));
|
||||
return EFI_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
/* Ex version */
|
||||
static EFI_STATUS EFIAPI
|
||||
FileWriteEx(IN EFI_FILE_PROTOCOL *This, IN OUT EFI_FILE_IO_TOKEN *Token)
|
||||
{
|
||||
return FileWrite(This, &(Token->BufferSize), Token->Buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set file position
|
||||
*
|
||||
* @v This File handle
|
||||
* @v Position New file position
|
||||
* @ret Status EFI status code
|
||||
*/
|
||||
static EFI_STATUS EFIAPI
|
||||
FileSetPosition(EFI_FILE_HANDLE This, UINT64 Position)
|
||||
{
|
||||
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
|
||||
UINT64 FileSize;
|
||||
|
||||
PrintInfo(L"SetPosition(" PERCENT_P L"|'%s', %lld) %s\n", (UINTN) This,
|
||||
FileName(File), Position, (File->IsDir)?L"<DIR>":L"");
|
||||
|
||||
/* If this is a directory, reset the Index to the start */
|
||||
if (File->IsDir) {
|
||||
if (Position != 0)
|
||||
return EFI_INVALID_PARAMETER;
|
||||
File->DirIndex = 0;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/* Fail if we attempt to seek past the end of the file (since
|
||||
* we do not support writes).
|
||||
*/
|
||||
FileSize = GrubGetFileSize(File);
|
||||
if (Position > FileSize) {
|
||||
PrintError(L"'%s': Cannot seek to #%llx of %llx\n",
|
||||
FileName(File), Position, FileSize);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/* Set position */
|
||||
GrubSetFileOffset(File, Position);
|
||||
PrintDebug(L"'%s': Position set to %llx\n",
|
||||
FileName(File), Position);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file position
|
||||
*
|
||||
* @v This File handle
|
||||
* @ret Position New file position
|
||||
* @ret Status EFI status code
|
||||
*/
|
||||
static EFI_STATUS EFIAPI
|
||||
FileGetPosition(EFI_FILE_HANDLE This, UINT64 *Position)
|
||||
{
|
||||
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
|
||||
|
||||
PrintInfo(L"GetPosition(" PERCENT_P L"|'%s', %lld)\n", (UINTN) This, FileName(File));
|
||||
|
||||
if (File->IsDir)
|
||||
*Position = File->DirIndex;
|
||||
else
|
||||
*Position = GrubGetFileOffset(File);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file information
|
||||
*
|
||||
* @v This File handle
|
||||
* @v Type Type of information
|
||||
* @v Len Buffer size
|
||||
* @v Data Buffer
|
||||
* @ret Status EFI status code
|
||||
*/
|
||||
static EFI_STATUS EFIAPI
|
||||
FileGetInfo(EFI_FILE_HANDLE This, EFI_GUID *Type, UINTN *Len, VOID *Data)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
|
||||
EFI_FILE_SYSTEM_INFO *FSInfo = (EFI_FILE_SYSTEM_INFO *) Data;
|
||||
EFI_FILE_INFO *Info = (EFI_FILE_INFO *) Data;
|
||||
EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *VLInfo = (EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *)Data;
|
||||
EFI_TIME Time;
|
||||
CHAR8* label;
|
||||
UINTN tmpLen;
|
||||
|
||||
PrintInfo(L"GetInfo(" PERCENT_P L"|'%s', %d) %s\n", (UINTN) This,
|
||||
FileName(File), *Len, File->IsDir?L"<DIR>":L"");
|
||||
|
||||
/* Determine information to return */
|
||||
if (CompareMem(Type, &gEfiFileInfoGuid, sizeof(*Type)) == 0) {
|
||||
|
||||
/* Fill file information */
|
||||
PrintExtra(L"Get regular file information\n");
|
||||
if (*Len < sizeof(EFI_FILE_INFO)) {
|
||||
*Len = MINIMUM_INFO_LENGTH;
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
ZeroMem(Data, sizeof(EFI_FILE_INFO));
|
||||
|
||||
Info->Attribute = EFI_FILE_READ_ONLY;
|
||||
GrubTimeToEfiTime(File->Mtime, &Time);
|
||||
CopyMem(&Info->CreateTime, &Time, sizeof(Time));
|
||||
CopyMem(&Info->LastAccessTime, &Time, sizeof(Time));
|
||||
CopyMem(&Info->ModificationTime, &Time, sizeof(Time));
|
||||
|
||||
if (File->IsDir) {
|
||||
Info->Attribute |= EFI_FILE_DIRECTORY;
|
||||
} else {
|
||||
Info->FileSize = GrubGetFileSize(File);
|
||||
Info->PhysicalSize = GrubGetFileSize(File);
|
||||
}
|
||||
|
||||
tmpLen = (UINTN)(Info->Size - sizeof(EFI_FILE_INFO) - 1);
|
||||
Status = Utf8ToUtf16NoAllocUpdateLen(File->basename, Info->FileName, &tmpLen);
|
||||
if (EFI_ERROR(Status)) {
|
||||
if (Status != EFI_BUFFER_TOO_SMALL) {
|
||||
PrintStatusError(Status, L"Could not convert basename to UTF-16");
|
||||
} else {
|
||||
*Len = MINIMUM_INFO_LENGTH;
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* The Info struct size already accounts for the extra NUL */
|
||||
Info->Size = sizeof(EFI_FILE_INFO) + tmpLen;
|
||||
*Len = (INTN)Info->Size;
|
||||
return EFI_SUCCESS;
|
||||
|
||||
} else if (CompareMem(Type, &gEfiFileSystemInfoGuid, sizeof(*Type)) == 0) {
|
||||
|
||||
/* Get file system information */
|
||||
PrintExtra(L"Get file system information\n");
|
||||
if (*Len < sizeof(EFI_FILE_SYSTEM_INFO)) {
|
||||
*Len = MINIMUM_FS_INFO_LENGTH;
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
ZeroMem(Data, sizeof(EFI_FILE_INFO));
|
||||
FSInfo->Size = *Len;
|
||||
FSInfo->ReadOnly = 1;
|
||||
/* NB: This should really be cluster size, but we don't have access to that */
|
||||
if (File->FileSystem->BlockIo2 != NULL) {
|
||||
FSInfo->BlockSize = File->FileSystem->BlockIo2->Media->BlockSize;
|
||||
} else {
|
||||
FSInfo->BlockSize = File->FileSystem->BlockIo->Media->BlockSize;
|
||||
}
|
||||
if (FSInfo->BlockSize == 0) {
|
||||
PrintWarning(L"Corrected Media BlockSize\n");
|
||||
FSInfo->BlockSize = 512;
|
||||
}
|
||||
if (File->FileSystem->BlockIo2 != NULL) {
|
||||
FSInfo->VolumeSize = (File->FileSystem->BlockIo2->Media->LastBlock + 1) *
|
||||
FSInfo->BlockSize;
|
||||
} else {
|
||||
FSInfo->VolumeSize = (File->FileSystem->BlockIo->Media->LastBlock + 1) *
|
||||
FSInfo->BlockSize;
|
||||
}
|
||||
/* No idea if we can easily get this for GRUB, and the device is RO anyway */
|
||||
FSInfo->FreeSpace = 0;
|
||||
|
||||
Status = GrubLabel(File, &label);
|
||||
if (EFI_ERROR(Status)) {
|
||||
PrintStatusError(Status, L"Could not read disk label");
|
||||
FSInfo->VolumeLabel[0] = 0;
|
||||
*Len = sizeof(EFI_FILE_SYSTEM_INFO);
|
||||
} else {
|
||||
tmpLen = (INTN)(FSInfo->Size - sizeof(EFI_FILE_SYSTEM_INFO) - 1);
|
||||
Status = Utf8ToUtf16NoAllocUpdateLen(label, FSInfo->VolumeLabel, &tmpLen);
|
||||
if (EFI_ERROR(Status)) {
|
||||
if (Status != EFI_BUFFER_TOO_SMALL) {
|
||||
PrintStatusError(Status, L"Could not convert label to UTF-16");
|
||||
} else {
|
||||
*Len = MINIMUM_FS_INFO_LENGTH;
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
FSInfo->Size = sizeof(EFI_FILE_SYSTEM_INFO) - 1 + tmpLen;
|
||||
*Len = (INTN)FSInfo->Size;
|
||||
}
|
||||
return EFI_SUCCESS;
|
||||
|
||||
} else if (CompareMem(Type, &gEfiFileSystemVolumeLabelInfoIdGuid, sizeof(*Type)) == 0) {
|
||||
|
||||
/* Get the volume label */
|
||||
Status = GrubLabel(File, &label);
|
||||
if (EFI_ERROR(Status)) {
|
||||
PrintStatusError(Status, L"Could not read disk label");
|
||||
}
|
||||
else {
|
||||
Status = Utf8ToUtf16NoAllocUpdateLen(label, VLInfo->VolumeLabel, Len);
|
||||
if (EFI_ERROR(Status)) {
|
||||
if (Status != EFI_BUFFER_TOO_SMALL)
|
||||
PrintStatusError(Status, L"Could not convert label to UTF-16");
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
return EFI_SUCCESS;
|
||||
|
||||
} else {
|
||||
|
||||
Print(L"'%s': Cannot get information of type ", FileName(File));
|
||||
PrintGuid(Type);
|
||||
Print(L"\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set file information
|
||||
*
|
||||
* @v This File handle
|
||||
* @v Type Type of information
|
||||
* @v Len Buffer size
|
||||
* @v Data Buffer
|
||||
* @ret Status EFI status code
|
||||
*/
|
||||
static EFI_STATUS EFIAPI
|
||||
FileSetInfo(EFI_FILE_HANDLE This, EFI_GUID *Type, UINTN Len, VOID *Data)
|
||||
{
|
||||
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
|
||||
|
||||
Print(L"Cannot set information of type ");
|
||||
PrintGuid(Type);
|
||||
Print(L" for file '%s'\n", FileName(File));
|
||||
|
||||
return EFI_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush file modified data
|
||||
*
|
||||
* @v This File handle
|
||||
* @v Type Type of information
|
||||
* @v Len Buffer size
|
||||
* @v Data Buffer
|
||||
* @ret Status EFI status code
|
||||
*/
|
||||
static EFI_STATUS EFIAPI
|
||||
FileFlush(EFI_FILE_HANDLE This)
|
||||
{
|
||||
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
|
||||
|
||||
PrintInfo(L"Flush(" PERCENT_P L"|'%s')\n", (UINTN) This, FileName(File));
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/* Ex version */
|
||||
static EFI_STATUS EFIAPI
|
||||
FileFlushEx(EFI_FILE_HANDLE This, EFI_FILE_IO_TOKEN *Token)
|
||||
{
|
||||
return FileFlush(This);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open root directory
|
||||
*
|
||||
* @v This EFI simple file system
|
||||
* @ret Root File handle for the root directory
|
||||
* @ret Status EFI status code
|
||||
*/
|
||||
EFI_STATUS EFIAPI
|
||||
FileOpenVolume(EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, EFI_FILE_HANDLE *Root)
|
||||
{
|
||||
EFI_FS *FSInstance = _CR(This, EFI_FS, FileIoInterface);
|
||||
|
||||
PrintInfo(L"OpenVolume\n");
|
||||
*Root = &FSInstance->RootFile->EfiFile;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Install the EFI simple file system protocol
|
||||
* If successful this call instantiates a new FS#: drive, that is made
|
||||
* available on the next 'map -r'. Note that all this call does is add
|
||||
* the FS protocol. OpenVolume won't be called until a process tries
|
||||
* to access a file or the root directory on the volume.
|
||||
*/
|
||||
EFI_STATUS
|
||||
FSInstall(EFI_FS *This, EFI_HANDLE ControllerHandle)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
/* Check if it's a filesystem we can handle */
|
||||
if (!GrubFSProbe(This))
|
||||
return EFI_UNSUPPORTED;
|
||||
|
||||
PrintInfo(L"FSInstall: %s\n", This->DevicePathString);
|
||||
|
||||
/* Initialize the root handle */
|
||||
Status = GrubCreateFile(&This->RootFile, This);
|
||||
if (EFI_ERROR(Status)) {
|
||||
PrintStatusError(Status, L"Could not create root file");
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Setup the EFI part */
|
||||
This->RootFile->EfiFile.Revision = EFI_FILE_PROTOCOL_REVISION2;
|
||||
This->RootFile->EfiFile.Open = FileOpen;
|
||||
This->RootFile->EfiFile.Close = FileClose;
|
||||
This->RootFile->EfiFile.Delete = FileDelete;
|
||||
This->RootFile->EfiFile.Read = FileRead;
|
||||
This->RootFile->EfiFile.Write = FileWrite;
|
||||
This->RootFile->EfiFile.GetPosition = FileGetPosition;
|
||||
This->RootFile->EfiFile.SetPosition = FileSetPosition;
|
||||
This->RootFile->EfiFile.GetInfo = FileGetInfo;
|
||||
This->RootFile->EfiFile.SetInfo = FileSetInfo;
|
||||
This->RootFile->EfiFile.Flush = FileFlush;
|
||||
This->RootFile->EfiFile.OpenEx = FileOpenEx;
|
||||
This->RootFile->EfiFile.ReadEx = FileReadEx;
|
||||
This->RootFile->EfiFile.WriteEx = FileWriteEx;
|
||||
This->RootFile->EfiFile.FlushEx = FileFlushEx;
|
||||
|
||||
/* Setup the other attributes */
|
||||
This->RootFile->path = "/";
|
||||
This->RootFile->basename = &This->RootFile->path[1];
|
||||
This->RootFile->IsDir = TRUE;
|
||||
|
||||
/* Install the simple file system protocol. */
|
||||
Status = BS->InstallMultipleProtocolInterfaces(&ControllerHandle,
|
||||
&gEfiSimpleFileSystemProtocolGuid, &This->FileIoInterface,
|
||||
NULL);
|
||||
if (EFI_ERROR(Status)) {
|
||||
PrintStatusError(Status, L"Could not install simple file system protocol");
|
||||
return Status;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/* Uninstall EFI simple file system protocol */
|
||||
VOID
|
||||
FSUninstall(EFI_FS *This, EFI_HANDLE ControllerHandle)
|
||||
{
|
||||
PrintInfo(L"FSUninstall: %s\n", This->DevicePathString);
|
||||
|
||||
BS->UninstallMultipleProtocolInterfaces(ControllerHandle,
|
||||
&gEfiSimpleFileSystemProtocolGuid, &This->FileIoInterface,
|
||||
NULL);
|
||||
}
|
86
EDK2/efiffs/mod/src/logging.c
Normal file
@@ -0,0 +1,86 @@
|
||||
/* logging.c - EFI logging */
|
||||
/*
|
||||
* Copyright © 2014-2017 Pete Batard <pete@akeo.ie>
|
||||
*
|
||||
* 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 "driver.h"
|
||||
|
||||
/* Not defined in gnu-efi yet */
|
||||
#define SHELL_VARIABLE_GUID { \
|
||||
0x158def5a, 0xf656, 0x419c, { 0xb0, 0x27, 0x7a, 0x31, 0x92, 0xc0, 0x79, 0xd2 } \
|
||||
}
|
||||
extern EFI_GUID gShellVariableGuid;
|
||||
EFI_GUID ShellVariable = SHELL_VARIABLE_GUID;
|
||||
|
||||
static UINTN PrintNone(IN CONST CHAR16 *fmt, ... ) { return 0; }
|
||||
Print_t PrintError = PrintNone;
|
||||
Print_t PrintWarning = PrintNone;
|
||||
Print_t PrintInfo = PrintNone;
|
||||
Print_t PrintDebug = PrintNone;
|
||||
Print_t PrintExtra = PrintNone;
|
||||
Print_t* PrintTable[] = { &PrintError, &PrintWarning, &PrintInfo,
|
||||
&PrintDebug, &PrintExtra };
|
||||
|
||||
/* Global driver verbosity level */
|
||||
#if !defined(DEFAULT_LOGLEVEL)
|
||||
#define DEFAULT_LOGLEVEL FS_LOGLEVEL_NONE
|
||||
#endif
|
||||
UINTN LogLevel = DEFAULT_LOGLEVEL;
|
||||
|
||||
/**
|
||||
* Print status
|
||||
*
|
||||
* @v Status EFI status code
|
||||
*/
|
||||
VOID
|
||||
PrintStatus(EFI_STATUS Status)
|
||||
{
|
||||
#if defined(__MAKEWITH_GNUEFI)
|
||||
CHAR16 StatusString[64];
|
||||
StatusToString(StatusString, Status);
|
||||
// Make sure the Status is unsigned 32 bits
|
||||
Print(L": [%d] %s\n", (Status & 0x7FFFFFFF), StatusString);
|
||||
#else
|
||||
Print(L": [%d]\n", (Status & 0x7FFFFFFF));
|
||||
#endif
|
||||
}
|
||||
|
||||
int g_fs_name_nocase = 0;
|
||||
/*
|
||||
* You can control the verbosity of the driver output by setting the shell environment
|
||||
* variable FS_LOGGING to one of the values defined in the FS_LOGLEVEL constants
|
||||
*/
|
||||
VOID
|
||||
SetLogging(VOID)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
CHAR16 LogVar[4];
|
||||
UINTN i, LogVarSize = sizeof(LogVar);
|
||||
|
||||
i = LogVarSize;
|
||||
Status = RT->GetVariable(L"FS_NAME_NOCASE", &ShellVariable, NULL, &i, LogVar);
|
||||
if (Status == EFI_SUCCESS)
|
||||
g_fs_name_nocase = 1;
|
||||
|
||||
Status = RT->GetVariable(L"FS_LOGGING", &ShellVariable, NULL, &LogVarSize, LogVar);
|
||||
if (Status == EFI_SUCCESS)
|
||||
LogLevel = Atoi(LogVar);
|
||||
|
||||
for (i=0; i<ARRAYSIZE(PrintTable); i++)
|
||||
*PrintTable[i] = (i < LogLevel)?(Print_t)Print:(Print_t)PrintNone;
|
||||
|
||||
PrintExtra(L"LogLevel = %d\n", LogLevel);
|
||||
}
|
1137
EDK2/efiffs/org/grub/grub-core/fs/iso9660.c
Normal file
784
EDK2/efiffs/org/src/file.c
Normal file
@@ -0,0 +1,784 @@
|
||||
/* file.c - SimpleFileIo Interface */
|
||||
/*
|
||||
* Copyright © 2014-2017 Pete Batard <pete@akeo.ie>
|
||||
* Based on iPXE's efi_driver.c and efi_file.c:
|
||||
* Copyright © 2011,2013 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 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 "driver.h"
|
||||
|
||||
/**
|
||||
* Get EFI file name (for debugging)
|
||||
*
|
||||
* @v file EFI file
|
||||
* @ret Name Name
|
||||
*/
|
||||
static const CHAR16 *
|
||||
FileName(EFI_GRUB_FILE *File)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
static CHAR16 Path[MAX_PATH];
|
||||
|
||||
Status = Utf8ToUtf16NoAlloc(File->path, Path, sizeof(Path));
|
||||
if (EFI_ERROR(Status)) {
|
||||
PrintStatusError(Status, L"Could not convert filename to UTF16");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return Path;
|
||||
}
|
||||
|
||||
/* Simple hook to populate the timestamp and directory flag when opening a file */
|
||||
static INT32
|
||||
InfoHook(const CHAR8 *name, const GRUB_DIRHOOK_INFO *Info, VOID *Data)
|
||||
{
|
||||
EFI_GRUB_FILE *File = (EFI_GRUB_FILE *) Data;
|
||||
|
||||
/* Look for a specific file */
|
||||
if (strcmpa(name, File->basename) != 0)
|
||||
return 0;
|
||||
|
||||
File->IsDir = (BOOLEAN) (Info->Dir);
|
||||
if (Info->MtimeSet)
|
||||
File->Mtime = Info->Mtime;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open file
|
||||
*
|
||||
* @v This File handle
|
||||
* @ret new New file handle
|
||||
* @v Name File name
|
||||
* @v Mode File mode
|
||||
* @v Attributes File attributes (for newly-created files)
|
||||
* @ret Status EFI status code
|
||||
*/
|
||||
static EFI_STATUS EFIAPI
|
||||
FileOpen(EFI_FILE_HANDLE This, EFI_FILE_HANDLE *New,
|
||||
CHAR16 *Name, UINT64 Mode, UINT64 Attributes)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
|
||||
EFI_GRUB_FILE *NewFile;
|
||||
|
||||
// TODO: Use dynamic buffers?
|
||||
char path[MAX_PATH], clean_path[MAX_PATH], *dirname;
|
||||
INTN i, len;
|
||||
BOOLEAN AbsolutePath = (*Name == L'\\');
|
||||
|
||||
PrintInfo(L"Open(" PERCENT_P L"%s, \"%s\")\n", (UINTN) This,
|
||||
IS_ROOT(File)?L" <ROOT>":L"", Name);
|
||||
|
||||
/* Fail unless opening read-only */
|
||||
if (Mode != EFI_FILE_MODE_READ) {
|
||||
PrintWarning(L"File '%s' can only be opened in read-only mode\n", Name);
|
||||
return EFI_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
/* Additional failures */
|
||||
if ((StrCmp(Name, L"..") == 0) && IS_ROOT(File)) {
|
||||
PrintInfo(L"Trying to open <ROOT>'s parent\n");
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
/* See if we're trying to reopen current (which the EFI Shell insists on doing) */
|
||||
if ((*Name == 0) || (StrCmp(Name, L".") == 0)) {
|
||||
PrintInfo(L" Reopening %s\n", IS_ROOT(File)?L"<ROOT>":FileName(File));
|
||||
File->RefCount++;
|
||||
*New = This;
|
||||
PrintInfo(L" RET: " PERCENT_P L"\n", (UINTN) *New);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/* If we have an absolute path, don't bother completing with the parent */
|
||||
if (AbsolutePath) {
|
||||
len = 0;
|
||||
} else {
|
||||
strcpya(path, File->path);
|
||||
len = strlena(path);
|
||||
/* Add delimiter if needed */
|
||||
if ((len == 0) || (path[len-1] != '/'))
|
||||
path[len++] = '/';
|
||||
}
|
||||
|
||||
/* Copy the rest of the path (converted to UTF-8) */
|
||||
Status = Utf16ToUtf8NoAlloc(Name, &path[len], sizeof(path) - len);
|
||||
if (EFI_ERROR(Status)) {
|
||||
PrintStatusError(Status, L"Could not convert path to UTF-8");
|
||||
return Status;
|
||||
}
|
||||
/* Convert the delimiters */
|
||||
for (i = strlena(path) - 1 ; i >= len; i--) {
|
||||
if (path[i] == '\\')
|
||||
path[i] = '/';
|
||||
}
|
||||
|
||||
/* We only want to handle with absolute paths */
|
||||
clean_path[0] = '/';
|
||||
/* Find out if we're dealing with root by removing the junk */
|
||||
CopyPathRelative(&clean_path[1], path, MAX_PATH - 1);
|
||||
if (clean_path[1] == 0) {
|
||||
/* We're dealing with the root */
|
||||
PrintInfo(L" Reopening <ROOT>\n");
|
||||
*New = &File->FileSystem->RootFile->EfiFile;
|
||||
/* Must make sure that DirIndex is reset too (NB: no concurrent access!) */
|
||||
File->FileSystem->RootFile->DirIndex = 0;
|
||||
PrintInfo(L" RET: " PERCENT_P L"\n", (UINTN) *New);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
// TODO: eventually we should seek for already opened files and increase RefCount
|
||||
/* Allocate and initialise an instance of a file */
|
||||
Status = GrubCreateFile(&NewFile, File->FileSystem);
|
||||
if (EFI_ERROR(Status)) {
|
||||
PrintStatusError(Status, L"Could not instantiate file");
|
||||
return Status;
|
||||
}
|
||||
|
||||
NewFile->path = AllocatePool(strlena(clean_path)+1);
|
||||
if (NewFile->path == NULL) {
|
||||
GrubDestroyFile(NewFile);
|
||||
PrintError(L"Could not instantiate path\n");
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
strcpya(NewFile->path, clean_path);
|
||||
|
||||
/* Isolate the basename and dirname */
|
||||
for (i = strlena(clean_path) - 1; i >= 0; i--) {
|
||||
if (clean_path[i] == '/') {
|
||||
clean_path[i] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
dirname = (i <= 0) ? "/" : clean_path;
|
||||
NewFile->basename = &NewFile->path[i+1];
|
||||
|
||||
/* Find if we're working with a directory and fill the grub timestamp */
|
||||
Status = GrubDir(NewFile, dirname, InfoHook, (VOID *) NewFile);
|
||||
if (EFI_ERROR(Status)) {
|
||||
if (Status != EFI_NOT_FOUND)
|
||||
PrintStatusError(Status, L"Could not get file attributes for '%s'", Name);
|
||||
FreePool(NewFile->path);
|
||||
GrubDestroyFile(NewFile);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Finally we can call on GRUB open() if it's a regular file */
|
||||
if (!NewFile->IsDir) {
|
||||
Status = GrubOpen(NewFile);
|
||||
if (EFI_ERROR(Status)) {
|
||||
if (Status != EFI_NOT_FOUND)
|
||||
PrintStatusError(Status, L"Could not open file '%s'", Name);
|
||||
FreePool(NewFile->path);
|
||||
GrubDestroyFile(NewFile);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
NewFile->RefCount++;
|
||||
*New = &NewFile->EfiFile;
|
||||
|
||||
PrintInfo(L" RET: " PERCENT_P L"\n", (UINTN) *New);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/* Ex version */
|
||||
static EFI_STATUS EFIAPI
|
||||
FileOpenEx(EFI_FILE_HANDLE This, EFI_FILE_HANDLE *New, CHAR16 *Name,
|
||||
UINT64 Mode, UINT64 Attributes, EFI_FILE_IO_TOKEN *Token)
|
||||
{
|
||||
return FileOpen(This, New, Name, Mode, Attributes);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Close file
|
||||
*
|
||||
* @v This File handle
|
||||
* @ret Status EFI status code
|
||||
*/
|
||||
static EFI_STATUS EFIAPI
|
||||
FileClose(EFI_FILE_HANDLE This)
|
||||
{
|
||||
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
|
||||
|
||||
PrintInfo(L"Close(" PERCENT_P L"|'%s') %s\n", (UINTN) This, FileName(File),
|
||||
IS_ROOT(File)?L"<ROOT>":L"");
|
||||
|
||||
/* Nothing to do it this is the root */
|
||||
if (IS_ROOT(File))
|
||||
return EFI_SUCCESS;
|
||||
|
||||
if (--File->RefCount == 0) {
|
||||
/* Close the file if it's a regular one */
|
||||
if (!File->IsDir)
|
||||
GrubClose(File);
|
||||
/* NB: basename points into File->path and does not need to be freed */
|
||||
if (File->path != NULL)
|
||||
FreePool(File->path);
|
||||
GrubDestroyFile(File);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close and delete file
|
||||
*
|
||||
* @v This File handle
|
||||
* @ret Status EFI status code
|
||||
*/
|
||||
static EFI_STATUS EFIAPI
|
||||
FileDelete(EFI_FILE_HANDLE This)
|
||||
{
|
||||
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
|
||||
|
||||
PrintError(L"Cannot delete '%s'\n", FileName(File));
|
||||
|
||||
/* Close file */
|
||||
FileClose(This);
|
||||
|
||||
/* Warn of failure to delete */
|
||||
return EFI_WARN_DELETE_FAILURE;
|
||||
}
|
||||
|
||||
/* GRUB uses a callback for each directory entry, whereas EFI uses repeated
|
||||
* firmware generated calls to FileReadDir() to get the info for each entry,
|
||||
* so we have to reconcile the twos. For now, we'll re-issue a call to GRUB
|
||||
* dir(), and run through all the entries (to find the one we
|
||||
* are interested in) multiple times. Maybe later we'll try to optimize this
|
||||
* by building a one-off chained list of entries that we can parse...
|
||||
*/
|
||||
static INT32
|
||||
DirHook(const CHAR8 *name, const GRUB_DIRHOOK_INFO *DirInfo, VOID *Data)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_FILE_INFO *Info = (EFI_FILE_INFO *) Data;
|
||||
INT64 *Index = (INT64 *) &Info->FileSize;
|
||||
CHAR8 *filename = (CHAR8 *) (UINTN) Info->PhysicalSize;
|
||||
EFI_TIME Time = { 1970, 01, 01, 00, 00, 00, 0, 0, 0, 0, 0};
|
||||
|
||||
// Eliminate '.' or '..'
|
||||
if ((name[0] == '.') && ((name[1] == 0) || ((name[1] == '.') && (name[2] == 0))))
|
||||
return 0;
|
||||
|
||||
/* Ignore any entry that doesn't match our index */
|
||||
if ((*Index)-- != 0)
|
||||
return 0;
|
||||
|
||||
strcpya(filename, name);
|
||||
|
||||
Status = Utf8ToUtf16NoAlloc(filename, Info->FileName, (INTN)(Info->Size - sizeof(EFI_FILE_INFO)));
|
||||
if (EFI_ERROR(Status)) {
|
||||
if (Status != EFI_BUFFER_TOO_SMALL)
|
||||
PrintStatusError(Status, L"Could not convert directory entry to UTF-8");
|
||||
return (INT32) Status;
|
||||
}
|
||||
/* The Info struct size already accounts for the extra NUL */
|
||||
Info->Size = sizeof(*Info) + StrLen(Info->FileName) * sizeof(CHAR16);
|
||||
|
||||
// Oh, and of course GRUB uses a 32 bit signed mtime value (seriously, wtf guys?!?)
|
||||
if (DirInfo->MtimeSet)
|
||||
GrubTimeToEfiTime(DirInfo->Mtime, &Time);
|
||||
CopyMem(&Info->CreateTime, &Time, sizeof(Time));
|
||||
CopyMem(&Info->LastAccessTime, &Time, sizeof(Time));
|
||||
CopyMem(&Info->ModificationTime, &Time, sizeof(Time));
|
||||
|
||||
Info->Attribute = EFI_FILE_READ_ONLY;
|
||||
if (DirInfo->Dir)
|
||||
Info->Attribute |= EFI_FILE_DIRECTORY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read directory entry
|
||||
*
|
||||
* @v file EFI file
|
||||
* @v Len Length to read
|
||||
* @v Data Data buffer
|
||||
* @ret Status EFI status code
|
||||
*/
|
||||
static EFI_STATUS
|
||||
FileReadDir(EFI_GRUB_FILE *File, UINTN *Len, VOID *Data)
|
||||
{
|
||||
EFI_FILE_INFO *Info = (EFI_FILE_INFO *) Data;
|
||||
EFI_STATUS Status;
|
||||
/* We temporarily repurpose the FileSize as a *signed* entry index */
|
||||
INT64 *Index = (INT64 *) &Info->FileSize;
|
||||
/* And PhysicalSize as a pointer to our filename */
|
||||
CHAR8 **basename = (CHAR8 **) &Info->PhysicalSize;
|
||||
CHAR8 path[MAX_PATH];
|
||||
EFI_GRUB_FILE *TmpFile = NULL;
|
||||
INTN len;
|
||||
|
||||
/* Unless we can fit our maximum size, forget it */
|
||||
if (*Len < MINIMUM_INFO_LENGTH) {
|
||||
*Len = MINIMUM_INFO_LENGTH;
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
/* Populate our Info template */
|
||||
ZeroMem(Data, *Len);
|
||||
Info->Size = *Len;
|
||||
*Index = File->DirIndex;
|
||||
strcpya(path, File->path);
|
||||
len = strlena(path);
|
||||
if (path[len-1] != '/')
|
||||
path[len++] = '/';
|
||||
*basename = &path[len];
|
||||
|
||||
/* Invoke GRUB's directory listing */
|
||||
Status = GrubDir(File, File->path, DirHook, Data);
|
||||
if (*Index >= 0) {
|
||||
/* No more entries */
|
||||
*Len = 0;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
if (EFI_ERROR(Status)) {
|
||||
PrintStatusError(Status, L"Directory listing failed");
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Our Index/FileSize must be reset */
|
||||
Info->FileSize = 0;
|
||||
Info->PhysicalSize = 0;
|
||||
|
||||
/* For regular files, we still need to fill the size */
|
||||
if (!(Info->Attribute & EFI_FILE_DIRECTORY)) {
|
||||
/* Open the file and read its size */
|
||||
Status = GrubCreateFile(&TmpFile, File->FileSystem);
|
||||
if (EFI_ERROR(Status)) {
|
||||
PrintStatusError(Status, L"Unable to create temporary file");
|
||||
return Status;
|
||||
}
|
||||
TmpFile->path = path;
|
||||
|
||||
Status = GrubOpen(TmpFile);
|
||||
if (EFI_ERROR(Status)) {
|
||||
// TODO: EFI_NO_MAPPING is returned for links...
|
||||
PrintStatusError(Status, L"Unable to obtain the size of '%s'", Info->FileName);
|
||||
/* Non fatal error */
|
||||
} else {
|
||||
Info->FileSize = GrubGetFileSize(TmpFile);
|
||||
Info->PhysicalSize = GrubGetFileSize(TmpFile);
|
||||
GrubClose(TmpFile);
|
||||
}
|
||||
GrubDestroyFile(TmpFile);
|
||||
}
|
||||
|
||||
*Len = (UINTN) Info->Size;
|
||||
/* Advance to the next entry */
|
||||
File->DirIndex++;
|
||||
|
||||
// PrintInfo(L" Entry[%d]: '%s' %s\n", File->DirIndex-1, Info->FileName,
|
||||
// (Info->Attribute&EFI_FILE_DIRECTORY)?L"<DIR>":L"");
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read from file
|
||||
*
|
||||
* @v This File handle
|
||||
* @v Len Length to read
|
||||
* @v Data Data buffer
|
||||
* @ret Status EFI status code
|
||||
*/
|
||||
static EFI_STATUS EFIAPI
|
||||
FileRead(EFI_FILE_HANDLE This, UINTN *Len, VOID *Data)
|
||||
{
|
||||
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
|
||||
|
||||
PrintInfo(L"Read(" PERCENT_P L"|'%s', %d) %s\n", (UINTN) This, FileName(File),
|
||||
*Len, File->IsDir?L"<DIR>":L"");
|
||||
|
||||
/* If this is a directory, then fetch the directory entries */
|
||||
if (File->IsDir)
|
||||
return FileReadDir(File, Len, Data);
|
||||
|
||||
return GrubRead(File, Data, Len);
|
||||
}
|
||||
|
||||
/* Ex version */
|
||||
static EFI_STATUS EFIAPI
|
||||
FileReadEx(IN EFI_FILE_PROTOCOL *This, IN OUT EFI_FILE_IO_TOKEN *Token)
|
||||
{
|
||||
return FileRead(This, &(Token->BufferSize), Token->Buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write to file
|
||||
*
|
||||
* @v This File handle
|
||||
* @v Len Length to write
|
||||
* @v Data Data buffer
|
||||
* @ret Status EFI status code
|
||||
*/
|
||||
static EFI_STATUS EFIAPI
|
||||
FileWrite(EFI_FILE_HANDLE This, UINTN *Len, VOID *Data)
|
||||
{
|
||||
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
|
||||
|
||||
PrintError(L"Cannot write to '%s'\n", FileName(File));
|
||||
return EFI_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
/* Ex version */
|
||||
static EFI_STATUS EFIAPI
|
||||
FileWriteEx(IN EFI_FILE_PROTOCOL *This, IN OUT EFI_FILE_IO_TOKEN *Token)
|
||||
{
|
||||
return FileWrite(This, &(Token->BufferSize), Token->Buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set file position
|
||||
*
|
||||
* @v This File handle
|
||||
* @v Position New file position
|
||||
* @ret Status EFI status code
|
||||
*/
|
||||
static EFI_STATUS EFIAPI
|
||||
FileSetPosition(EFI_FILE_HANDLE This, UINT64 Position)
|
||||
{
|
||||
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
|
||||
UINT64 FileSize;
|
||||
|
||||
PrintInfo(L"SetPosition(" PERCENT_P L"|'%s', %lld) %s\n", (UINTN) This,
|
||||
FileName(File), Position, (File->IsDir)?L"<DIR>":L"");
|
||||
|
||||
/* If this is a directory, reset the Index to the start */
|
||||
if (File->IsDir) {
|
||||
if (Position != 0)
|
||||
return EFI_INVALID_PARAMETER;
|
||||
File->DirIndex = 0;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/* Fail if we attempt to seek past the end of the file (since
|
||||
* we do not support writes).
|
||||
*/
|
||||
FileSize = GrubGetFileSize(File);
|
||||
if (Position > FileSize) {
|
||||
PrintError(L"'%s': Cannot seek to #%llx of %llx\n",
|
||||
FileName(File), Position, FileSize);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/* Set position */
|
||||
GrubSetFileOffset(File, Position);
|
||||
PrintDebug(L"'%s': Position set to %llx\n",
|
||||
FileName(File), Position);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file position
|
||||
*
|
||||
* @v This File handle
|
||||
* @ret Position New file position
|
||||
* @ret Status EFI status code
|
||||
*/
|
||||
static EFI_STATUS EFIAPI
|
||||
FileGetPosition(EFI_FILE_HANDLE This, UINT64 *Position)
|
||||
{
|
||||
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
|
||||
|
||||
PrintInfo(L"GetPosition(" PERCENT_P L"|'%s', %lld)\n", (UINTN) This, FileName(File));
|
||||
|
||||
if (File->IsDir)
|
||||
*Position = File->DirIndex;
|
||||
else
|
||||
*Position = GrubGetFileOffset(File);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file information
|
||||
*
|
||||
* @v This File handle
|
||||
* @v Type Type of information
|
||||
* @v Len Buffer size
|
||||
* @v Data Buffer
|
||||
* @ret Status EFI status code
|
||||
*/
|
||||
static EFI_STATUS EFIAPI
|
||||
FileGetInfo(EFI_FILE_HANDLE This, EFI_GUID *Type, UINTN *Len, VOID *Data)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
|
||||
EFI_FILE_SYSTEM_INFO *FSInfo = (EFI_FILE_SYSTEM_INFO *) Data;
|
||||
EFI_FILE_INFO *Info = (EFI_FILE_INFO *) Data;
|
||||
EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *VLInfo = (EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *)Data;
|
||||
EFI_TIME Time;
|
||||
CHAR8* label;
|
||||
UINTN tmpLen;
|
||||
|
||||
PrintInfo(L"GetInfo(" PERCENT_P L"|'%s', %d) %s\n", (UINTN) This,
|
||||
FileName(File), *Len, File->IsDir?L"<DIR>":L"");
|
||||
|
||||
/* Determine information to return */
|
||||
if (CompareMem(Type, &gEfiFileInfoGuid, sizeof(*Type)) == 0) {
|
||||
|
||||
/* Fill file information */
|
||||
PrintExtra(L"Get regular file information\n");
|
||||
if (*Len < MINIMUM_INFO_LENGTH) {
|
||||
*Len = MINIMUM_INFO_LENGTH;
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
ZeroMem(Data, sizeof(EFI_FILE_INFO));
|
||||
|
||||
Info->Attribute = EFI_FILE_READ_ONLY;
|
||||
GrubTimeToEfiTime(File->Mtime, &Time);
|
||||
CopyMem(&Info->CreateTime, &Time, sizeof(Time));
|
||||
CopyMem(&Info->LastAccessTime, &Time, sizeof(Time));
|
||||
CopyMem(&Info->ModificationTime, &Time, sizeof(Time));
|
||||
|
||||
if (File->IsDir) {
|
||||
Info->Attribute |= EFI_FILE_DIRECTORY;
|
||||
} else {
|
||||
Info->FileSize = GrubGetFileSize(File);
|
||||
Info->PhysicalSize = GrubGetFileSize(File);
|
||||
}
|
||||
|
||||
tmpLen = (UINTN)(Info->Size - sizeof(EFI_FILE_INFO) - 1);
|
||||
Status = Utf8ToUtf16NoAllocUpdateLen(File->basename, Info->FileName, &tmpLen);
|
||||
if (EFI_ERROR(Status)) {
|
||||
if (Status != EFI_BUFFER_TOO_SMALL)
|
||||
PrintStatusError(Status, L"Could not convert basename to UTF-16");
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* The Info struct size already accounts for the extra NUL */
|
||||
Info->Size = sizeof(EFI_FILE_INFO) + tmpLen;
|
||||
*Len = (INTN)Info->Size;
|
||||
return EFI_SUCCESS;
|
||||
|
||||
} else if (CompareMem(Type, &gEfiFileSystemInfoGuid, sizeof(*Type)) == 0) {
|
||||
|
||||
/* Get file system information */
|
||||
PrintExtra(L"Get file system information\n");
|
||||
if (*Len < MINIMUM_FS_INFO_LENGTH) {
|
||||
*Len = MINIMUM_FS_INFO_LENGTH;
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
ZeroMem(Data, sizeof(EFI_FILE_INFO));
|
||||
FSInfo->Size = *Len;
|
||||
FSInfo->ReadOnly = 1;
|
||||
/* NB: This should really be cluster size, but we don't have access to that */
|
||||
if (File->FileSystem->BlockIo2 != NULL) {
|
||||
FSInfo->BlockSize = File->FileSystem->BlockIo2->Media->BlockSize;
|
||||
} else {
|
||||
FSInfo->BlockSize = File->FileSystem->BlockIo->Media->BlockSize;
|
||||
}
|
||||
if (FSInfo->BlockSize == 0) {
|
||||
PrintWarning(L"Corrected Media BlockSize\n");
|
||||
FSInfo->BlockSize = 512;
|
||||
}
|
||||
if (File->FileSystem->BlockIo2 != NULL) {
|
||||
FSInfo->VolumeSize = (File->FileSystem->BlockIo2->Media->LastBlock + 1) *
|
||||
FSInfo->BlockSize;
|
||||
} else {
|
||||
FSInfo->VolumeSize = (File->FileSystem->BlockIo->Media->LastBlock + 1) *
|
||||
FSInfo->BlockSize;
|
||||
}
|
||||
/* No idea if we can easily get this for GRUB, and the device is RO anyway */
|
||||
FSInfo->FreeSpace = 0;
|
||||
|
||||
Status = GrubLabel(File, &label);
|
||||
if (EFI_ERROR(Status)) {
|
||||
PrintStatusError(Status, L"Could not read disk label");
|
||||
FSInfo->VolumeLabel[0] = 0;
|
||||
*Len = sizeof(EFI_FILE_SYSTEM_INFO);
|
||||
} else {
|
||||
tmpLen = (INTN)(FSInfo->Size - sizeof(EFI_FILE_SYSTEM_INFO) - 1);
|
||||
Status = Utf8ToUtf16NoAllocUpdateLen(label, FSInfo->VolumeLabel, &tmpLen);
|
||||
if (EFI_ERROR(Status)) {
|
||||
if (Status != EFI_BUFFER_TOO_SMALL)
|
||||
PrintStatusError(Status, L"Could not convert label to UTF-16");
|
||||
return Status;
|
||||
}
|
||||
FSInfo->Size = sizeof(EFI_FILE_SYSTEM_INFO) - 1 + tmpLen;
|
||||
*Len = (INTN)FSInfo->Size;
|
||||
}
|
||||
return EFI_SUCCESS;
|
||||
|
||||
} else if (CompareMem(Type, &gEfiFileSystemVolumeLabelInfoIdGuid, sizeof(*Type)) == 0) {
|
||||
|
||||
/* Get the volume label */
|
||||
Status = GrubLabel(File, &label);
|
||||
if (EFI_ERROR(Status)) {
|
||||
PrintStatusError(Status, L"Could not read disk label");
|
||||
}
|
||||
else {
|
||||
Status = Utf8ToUtf16NoAllocUpdateLen(label, VLInfo->VolumeLabel, Len);
|
||||
if (EFI_ERROR(Status)) {
|
||||
if (Status != EFI_BUFFER_TOO_SMALL)
|
||||
PrintStatusError(Status, L"Could not convert label to UTF-16");
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
return EFI_SUCCESS;
|
||||
|
||||
} else {
|
||||
|
||||
Print(L"'%s': Cannot get information of type ", FileName(File));
|
||||
PrintGuid(Type);
|
||||
Print(L"\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set file information
|
||||
*
|
||||
* @v This File handle
|
||||
* @v Type Type of information
|
||||
* @v Len Buffer size
|
||||
* @v Data Buffer
|
||||
* @ret Status EFI status code
|
||||
*/
|
||||
static EFI_STATUS EFIAPI
|
||||
FileSetInfo(EFI_FILE_HANDLE This, EFI_GUID *Type, UINTN Len, VOID *Data)
|
||||
{
|
||||
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
|
||||
|
||||
Print(L"Cannot set information of type ");
|
||||
PrintGuid(Type);
|
||||
Print(L" for file '%s'\n", FileName(File));
|
||||
|
||||
return EFI_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush file modified data
|
||||
*
|
||||
* @v This File handle
|
||||
* @v Type Type of information
|
||||
* @v Len Buffer size
|
||||
* @v Data Buffer
|
||||
* @ret Status EFI status code
|
||||
*/
|
||||
static EFI_STATUS EFIAPI
|
||||
FileFlush(EFI_FILE_HANDLE This)
|
||||
{
|
||||
EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
|
||||
|
||||
PrintInfo(L"Flush(" PERCENT_P L"|'%s')\n", (UINTN) This, FileName(File));
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/* Ex version */
|
||||
static EFI_STATUS EFIAPI
|
||||
FileFlushEx(EFI_FILE_HANDLE This, EFI_FILE_IO_TOKEN *Token)
|
||||
{
|
||||
return FileFlush(This);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open root directory
|
||||
*
|
||||
* @v This EFI simple file system
|
||||
* @ret Root File handle for the root directory
|
||||
* @ret Status EFI status code
|
||||
*/
|
||||
EFI_STATUS EFIAPI
|
||||
FileOpenVolume(EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, EFI_FILE_HANDLE *Root)
|
||||
{
|
||||
EFI_FS *FSInstance = _CR(This, EFI_FS, FileIoInterface);
|
||||
|
||||
PrintInfo(L"OpenVolume\n");
|
||||
*Root = &FSInstance->RootFile->EfiFile;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Install the EFI simple file system protocol
|
||||
* If successful this call instantiates a new FS#: drive, that is made
|
||||
* available on the next 'map -r'. Note that all this call does is add
|
||||
* the FS protocol. OpenVolume won't be called until a process tries
|
||||
* to access a file or the root directory on the volume.
|
||||
*/
|
||||
EFI_STATUS
|
||||
FSInstall(EFI_FS *This, EFI_HANDLE ControllerHandle)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
/* Check if it's a filesystem we can handle */
|
||||
if (!GrubFSProbe(This))
|
||||
return EFI_UNSUPPORTED;
|
||||
|
||||
PrintInfo(L"FSInstall: %s\n", This->DevicePathString);
|
||||
|
||||
/* Initialize the root handle */
|
||||
Status = GrubCreateFile(&This->RootFile, This);
|
||||
if (EFI_ERROR(Status)) {
|
||||
PrintStatusError(Status, L"Could not create root file");
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Setup the EFI part */
|
||||
This->RootFile->EfiFile.Revision = EFI_FILE_PROTOCOL_REVISION2;
|
||||
This->RootFile->EfiFile.Open = FileOpen;
|
||||
This->RootFile->EfiFile.Close = FileClose;
|
||||
This->RootFile->EfiFile.Delete = FileDelete;
|
||||
This->RootFile->EfiFile.Read = FileRead;
|
||||
This->RootFile->EfiFile.Write = FileWrite;
|
||||
This->RootFile->EfiFile.GetPosition = FileGetPosition;
|
||||
This->RootFile->EfiFile.SetPosition = FileSetPosition;
|
||||
This->RootFile->EfiFile.GetInfo = FileGetInfo;
|
||||
This->RootFile->EfiFile.SetInfo = FileSetInfo;
|
||||
This->RootFile->EfiFile.Flush = FileFlush;
|
||||
This->RootFile->EfiFile.OpenEx = FileOpenEx;
|
||||
This->RootFile->EfiFile.ReadEx = FileReadEx;
|
||||
This->RootFile->EfiFile.WriteEx = FileWriteEx;
|
||||
This->RootFile->EfiFile.FlushEx = FileFlushEx;
|
||||
|
||||
/* Setup the other attributes */
|
||||
This->RootFile->path = "/";
|
||||
This->RootFile->basename = &This->RootFile->path[1];
|
||||
This->RootFile->IsDir = TRUE;
|
||||
|
||||
/* Install the simple file system protocol. */
|
||||
Status = BS->InstallMultipleProtocolInterfaces(&ControllerHandle,
|
||||
&gEfiSimpleFileSystemProtocolGuid, &This->FileIoInterface,
|
||||
NULL);
|
||||
if (EFI_ERROR(Status)) {
|
||||
PrintStatusError(Status, L"Could not install simple file system protocol");
|
||||
return Status;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/* Uninstall EFI simple file system protocol */
|
||||
VOID
|
||||
FSUninstall(EFI_FS *This, EFI_HANDLE ControllerHandle)
|
||||
{
|
||||
PrintInfo(L"FSUninstall: %s\n", This->DevicePathString);
|
||||
|
||||
BS->UninstallMultipleProtocolInterfaces(ControllerHandle,
|
||||
&gEfiSimpleFileSystemProtocolGuid, &This->FileIoInterface,
|
||||
NULL);
|
||||
}
|
80
EDK2/efiffs/org/src/logging.c
Normal file
@@ -0,0 +1,80 @@
|
||||
/* logging.c - EFI logging */
|
||||
/*
|
||||
* Copyright © 2014-2017 Pete Batard <pete@akeo.ie>
|
||||
*
|
||||
* 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 "driver.h"
|
||||
|
||||
/* Not defined in gnu-efi yet */
|
||||
#define SHELL_VARIABLE_GUID { \
|
||||
0x158def5a, 0xf656, 0x419c, { 0xb0, 0x27, 0x7a, 0x31, 0x92, 0xc0, 0x79, 0xd2 } \
|
||||
}
|
||||
extern EFI_GUID gShellVariableGuid;
|
||||
EFI_GUID ShellVariable = SHELL_VARIABLE_GUID;
|
||||
|
||||
static UINTN PrintNone(IN CONST CHAR16 *fmt, ... ) { return 0; }
|
||||
Print_t PrintError = PrintNone;
|
||||
Print_t PrintWarning = PrintNone;
|
||||
Print_t PrintInfo = PrintNone;
|
||||
Print_t PrintDebug = PrintNone;
|
||||
Print_t PrintExtra = PrintNone;
|
||||
Print_t* PrintTable[] = { &PrintError, &PrintWarning, &PrintInfo,
|
||||
&PrintDebug, &PrintExtra };
|
||||
|
||||
/* Global driver verbosity level */
|
||||
#if !defined(DEFAULT_LOGLEVEL)
|
||||
#define DEFAULT_LOGLEVEL FS_LOGLEVEL_NONE
|
||||
#endif
|
||||
UINTN LogLevel = DEFAULT_LOGLEVEL;
|
||||
|
||||
/**
|
||||
* Print status
|
||||
*
|
||||
* @v Status EFI status code
|
||||
*/
|
||||
VOID
|
||||
PrintStatus(EFI_STATUS Status)
|
||||
{
|
||||
#if defined(__MAKEWITH_GNUEFI)
|
||||
CHAR16 StatusString[64];
|
||||
StatusToString(StatusString, Status);
|
||||
// Make sure the Status is unsigned 32 bits
|
||||
Print(L": [%d] %s\n", (Status & 0x7FFFFFFF), StatusString);
|
||||
#else
|
||||
Print(L": [%d]\n", (Status & 0x7FFFFFFF));
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* You can control the verbosity of the driver output by setting the shell environment
|
||||
* variable FS_LOGGING to one of the values defined in the FS_LOGLEVEL constants
|
||||
*/
|
||||
VOID
|
||||
SetLogging(VOID)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
CHAR16 LogVar[4];
|
||||
UINTN i, LogVarSize = sizeof(LogVar);
|
||||
|
||||
Status = RT->GetVariable(L"FS_LOGGING", &ShellVariable, NULL, &LogVarSize, LogVar);
|
||||
if (Status == EFI_SUCCESS)
|
||||
LogLevel = Atoi(LogVar);
|
||||
|
||||
for (i=0; i<ARRAYSIZE(PrintTable); i++)
|
||||
*PrintTable[i] = (i < LogLevel)?(Print_t)Print:(Print_t)PrintNone;
|
||||
|
||||
PrintExtra(L"LogLevel = %d\n", LogLevel);
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
Please download exfat-1.3.0.zip and mirrors-libfuse-fuse-2.9.9.zip first.
|
||||
|
||||
exfat-1.3.0.zip:
|
||||
https://codeload.github.com/relan/exfat/zip/v1.3.0
|
||||
|
||||
mirrors-libfuse-fuse-2.9.9.zip:
|
||||
https://gitee.com/mirrors/libfuse/repository/archive/fuse-2.9.9.zip
|
||||
|
@@ -18,14 +18,14 @@ if ! [ -e LIBFUSE ]; then
|
||||
./buidlibfuse.sh
|
||||
fi
|
||||
|
||||
|
||||
rm -f EXFAT/shared/*
|
||||
rm -f EXFAT/static/*
|
||||
rm -rf EXFAT
|
||||
mkdir -p EXFAT/shared
|
||||
mkdir -p EXFAT/static
|
||||
|
||||
|
||||
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
|
||||
@@ -42,6 +42,8 @@ cd ..
|
||||
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
|
||||
|
@@ -5,10 +5,14 @@ CUR="$PWD"
|
||||
rm -rf libfuse
|
||||
rm -rf LIBFUSE
|
||||
|
||||
unzip mirrors-libfuse-fuse-2.9.9.zip
|
||||
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
|
||||
|
||||
|
||||
cd libfuse
|
||||
./makeconf.sh
|
||||
|
||||
./configure --prefix="$CUR/LIBFUSE"
|
||||
|
@@ -2,8 +2,7 @@
|
||||
|
||||
CUR="$PWD"
|
||||
|
||||
#LIBFUSE_DIR=$CUR/LIBFUSE
|
||||
LIBFUSE_DIR=../ExFAT/LIBFUSE
|
||||
LIBFUSE_DIR=$CUR/LIBFUSE
|
||||
|
||||
if uname -a | egrep -q 'x86_64|amd64'; then
|
||||
name=vtoy_fuse_iso_64
|
||||
|
@@ -14,16 +14,21 @@ LIBFUSE_DIR=$CUR/LIBFUSE
|
||||
rm -rf libfuse
|
||||
rm -rf $LIBFUSE_DIR
|
||||
|
||||
# please download https://gitee.com/mirrors/libfuse/repository/archive/fuse-2.9.9.zip
|
||||
if ! [ -e mirrors-libfuse-fuse-2.9.9.zip ]; then
|
||||
# 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
|
||||
|
||||
unzip mirrors-libfuse-fuse-2.9.9.zip
|
||||
|
||||
|
||||
cd libfuse
|
||||
./makeconf.sh
|
||||
|
||||
./configure --prefix="$LIBFUSE_DIR"
|
||||
|
BIN
FUSEISO/vtoy_fuse_iso_32
Normal file
BIN
FUSEISO/vtoy_fuse_iso_64
Normal file
@@ -1578,10 +1578,12 @@ 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_plugin.c;
|
||||
common = ventoy/ventoy_json.c;
|
||||
common = ventoy/lzx.c;
|
||||
common = ventoy/xpress.c;
|
||||
common = ventoy/huffman.c;
|
||||
};
|
||||
|
491
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/test.c
Normal file
@@ -0,0 +1,491 @@
|
||||
/* test.c -- The test command.. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2005,2007,2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/dl.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/fs.h>
|
||||
#include <grub/device.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static int g_test_case_insensitive = 0;
|
||||
|
||||
/* A simple implementation for signed numbers. */
|
||||
static int
|
||||
grub_strtosl (char *arg, char **end, int base)
|
||||
{
|
||||
if (arg[0] == '-')
|
||||
return -grub_strtoul (arg + 1, end, base);
|
||||
return grub_strtoul (arg, end, base);
|
||||
}
|
||||
|
||||
/* Context for test_parse. */
|
||||
struct test_parse_ctx
|
||||
{
|
||||
int invert;
|
||||
int or, and;
|
||||
int file_exists;
|
||||
struct grub_dirhook_info file_info;
|
||||
char *filename;
|
||||
};
|
||||
|
||||
/* Take care of discarding and inverting. */
|
||||
static void
|
||||
update_val (int val, struct test_parse_ctx *ctx)
|
||||
{
|
||||
ctx->and = ctx->and && (ctx->invert ? ! val : val);
|
||||
ctx->invert = 0;
|
||||
}
|
||||
|
||||
/* A hook for iterating directories. */
|
||||
static int
|
||||
find_file (const char *cur_filename, const struct grub_dirhook_info *info,
|
||||
void *data)
|
||||
{
|
||||
int case_insensitive = 0;
|
||||
struct test_parse_ctx *ctx = data;
|
||||
|
||||
if (g_test_case_insensitive || info->case_insensitive)
|
||||
case_insensitive = 1;
|
||||
|
||||
if ((case_insensitive ? grub_strcasecmp (cur_filename, ctx->filename)
|
||||
: grub_strcmp (cur_filename, ctx->filename)) == 0)
|
||||
{
|
||||
ctx->file_info = *info;
|
||||
ctx->file_exists = 1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check if file exists and fetch its information. */
|
||||
static void
|
||||
get_fileinfo (char *path, struct test_parse_ctx *ctx)
|
||||
{
|
||||
char *pathname;
|
||||
char *device_name;
|
||||
grub_fs_t fs;
|
||||
grub_device_t dev;
|
||||
|
||||
ctx->file_exists = 0;
|
||||
device_name = grub_file_get_device_name (path);
|
||||
dev = grub_device_open (device_name);
|
||||
if (! dev)
|
||||
{
|
||||
grub_free (device_name);
|
||||
return;
|
||||
}
|
||||
|
||||
fs = grub_fs_probe (dev);
|
||||
if (! fs)
|
||||
{
|
||||
grub_free (device_name);
|
||||
grub_device_close (dev);
|
||||
return;
|
||||
}
|
||||
|
||||
pathname = grub_strchr (path, ')');
|
||||
if (! pathname)
|
||||
pathname = path;
|
||||
else
|
||||
pathname++;
|
||||
|
||||
/* Remove trailing '/'. */
|
||||
while (*pathname && pathname[grub_strlen (pathname) - 1] == '/')
|
||||
pathname[grub_strlen (pathname) - 1] = 0;
|
||||
|
||||
/* Split into path and filename. */
|
||||
ctx->filename = grub_strrchr (pathname, '/');
|
||||
if (! ctx->filename)
|
||||
{
|
||||
path = grub_strdup ("/");
|
||||
ctx->filename = pathname;
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx->filename++;
|
||||
path = grub_strdup (pathname);
|
||||
path[ctx->filename - pathname] = 0;
|
||||
}
|
||||
|
||||
/* It's the whole device. */
|
||||
if (! *pathname)
|
||||
{
|
||||
ctx->file_exists = 1;
|
||||
grub_memset (&ctx->file_info, 0, sizeof (ctx->file_info));
|
||||
/* Root is always a directory. */
|
||||
ctx->file_info.dir = 1;
|
||||
|
||||
/* Fetch writing time. */
|
||||
ctx->file_info.mtimeset = 0;
|
||||
if (fs->fs_mtime)
|
||||
{
|
||||
if (! fs->fs_mtime (dev, &ctx->file_info.mtime))
|
||||
ctx->file_info.mtimeset = 1;
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
}
|
||||
else
|
||||
(fs->fs_dir) (dev, path, find_file, ctx);
|
||||
|
||||
grub_device_close (dev);
|
||||
grub_free (path);
|
||||
grub_free (device_name);
|
||||
}
|
||||
|
||||
/* Parse a test expression starting from *argn. */
|
||||
static int
|
||||
test_parse (char **args, int *argn, int argc)
|
||||
{
|
||||
struct test_parse_ctx ctx = {
|
||||
.and = 1,
|
||||
.or = 0,
|
||||
.invert = 0
|
||||
};
|
||||
|
||||
/* Here we have the real parsing. */
|
||||
while (*argn < argc)
|
||||
{
|
||||
/* First try 3 argument tests. */
|
||||
if (*argn + 2 < argc)
|
||||
{
|
||||
/* String tests. */
|
||||
if (grub_strcmp (args[*argn + 1], "=") == 0
|
||||
|| grub_strcmp (args[*argn + 1], "==") == 0)
|
||||
{
|
||||
update_val (grub_strcmp (args[*argn], args[*argn + 2]) == 0,
|
||||
&ctx);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn + 1], "!=") == 0)
|
||||
{
|
||||
update_val (grub_strcmp (args[*argn], args[*argn + 2]) != 0,
|
||||
&ctx);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* GRUB extension: lexicographical sorting. */
|
||||
if (grub_strcmp (args[*argn + 1], "<") == 0)
|
||||
{
|
||||
update_val (grub_strcmp (args[*argn], args[*argn + 2]) < 0,
|
||||
&ctx);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn + 1], "<=") == 0)
|
||||
{
|
||||
update_val (grub_strcmp (args[*argn], args[*argn + 2]) <= 0,
|
||||
&ctx);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn + 1], ">") == 0)
|
||||
{
|
||||
update_val (grub_strcmp (args[*argn], args[*argn + 2]) > 0,
|
||||
&ctx);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn + 1], ">=") == 0)
|
||||
{
|
||||
update_val (grub_strcmp (args[*argn], args[*argn + 2]) >= 0,
|
||||
&ctx);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Number tests. */
|
||||
if (grub_strcmp (args[*argn + 1], "-eq") == 0)
|
||||
{
|
||||
update_val (grub_strtosl (args[*argn], 0, 0)
|
||||
== grub_strtosl (args[*argn + 2], 0, 0), &ctx);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn + 1], "-ge") == 0)
|
||||
{
|
||||
update_val (grub_strtosl (args[*argn], 0, 0)
|
||||
>= grub_strtosl (args[*argn + 2], 0, 0), &ctx);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn + 1], "-gt") == 0)
|
||||
{
|
||||
update_val (grub_strtosl (args[*argn], 0, 0)
|
||||
> grub_strtosl (args[*argn + 2], 0, 0), &ctx);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn + 1], "-le") == 0)
|
||||
{
|
||||
update_val (grub_strtosl (args[*argn], 0, 0)
|
||||
<= grub_strtosl (args[*argn + 2], 0, 0), &ctx);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn + 1], "-lt") == 0)
|
||||
{
|
||||
update_val (grub_strtosl (args[*argn], 0, 0)
|
||||
< grub_strtosl (args[*argn + 2], 0, 0), &ctx);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn + 1], "-ne") == 0)
|
||||
{
|
||||
update_val (grub_strtosl (args[*argn], 0, 0)
|
||||
!= grub_strtosl (args[*argn + 2], 0, 0), &ctx);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* GRUB extension: compare numbers skipping prefixes.
|
||||
Useful for comparing versions. E.g. vmlinuz-2 -plt vmlinuz-11. */
|
||||
if (grub_strcmp (args[*argn + 1], "-pgt") == 0
|
||||
|| grub_strcmp (args[*argn + 1], "-plt") == 0)
|
||||
{
|
||||
int i;
|
||||
/* Skip common prefix. */
|
||||
for (i = 0; args[*argn][i] == args[*argn + 2][i]
|
||||
&& args[*argn][i]; i++);
|
||||
|
||||
/* Go the digits back. */
|
||||
i--;
|
||||
while (grub_isdigit (args[*argn][i]) && i > 0)
|
||||
i--;
|
||||
i++;
|
||||
|
||||
if (grub_strcmp (args[*argn + 1], "-pgt") == 0)
|
||||
update_val (grub_strtoul (args[*argn] + i, 0, 0)
|
||||
> grub_strtoul (args[*argn + 2] + i, 0, 0), &ctx);
|
||||
else
|
||||
update_val (grub_strtoul (args[*argn] + i, 0, 0)
|
||||
< grub_strtoul (args[*argn + 2] + i, 0, 0), &ctx);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* -nt and -ot tests. GRUB extension: when doing -?t<bias> bias
|
||||
will be added to the first mtime. */
|
||||
if (grub_memcmp (args[*argn + 1], "-nt", 3) == 0
|
||||
|| grub_memcmp (args[*argn + 1], "-ot", 3) == 0)
|
||||
{
|
||||
struct grub_dirhook_info file1;
|
||||
int file1exists;
|
||||
int bias = 0;
|
||||
|
||||
/* Fetch fileinfo. */
|
||||
get_fileinfo (args[*argn], &ctx);
|
||||
file1 = ctx.file_info;
|
||||
file1exists = ctx.file_exists;
|
||||
get_fileinfo (args[*argn + 2], &ctx);
|
||||
|
||||
if (args[*argn + 1][3])
|
||||
bias = grub_strtosl (args[*argn + 1] + 3, 0, 0);
|
||||
|
||||
if (grub_memcmp (args[*argn + 1], "-nt", 3) == 0)
|
||||
update_val ((file1exists && ! ctx.file_exists)
|
||||
|| (file1.mtimeset && ctx.file_info.mtimeset
|
||||
&& file1.mtime + bias > ctx.file_info.mtime),
|
||||
&ctx);
|
||||
else
|
||||
update_val ((! file1exists && ctx.file_exists)
|
||||
|| (file1.mtimeset && ctx.file_info.mtimeset
|
||||
&& file1.mtime + bias < ctx.file_info.mtime),
|
||||
&ctx);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Two-argument tests. */
|
||||
if (*argn + 1 < argc)
|
||||
{
|
||||
/* File tests. */
|
||||
if (grub_strcmp (args[*argn], "-d") == 0)
|
||||
{
|
||||
get_fileinfo (args[*argn + 1], &ctx);
|
||||
update_val (ctx.file_exists && ctx.file_info.dir, &ctx);
|
||||
(*argn) += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn], "-D") == 0)
|
||||
{
|
||||
g_test_case_insensitive = 1;
|
||||
get_fileinfo (args[*argn + 1], &ctx);
|
||||
g_test_case_insensitive = 0;
|
||||
update_val (ctx.file_exists && ctx.file_info.dir, &ctx);
|
||||
(*argn) += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn], "-e") == 0)
|
||||
{
|
||||
get_fileinfo (args[*argn + 1], &ctx);
|
||||
update_val (ctx.file_exists, &ctx);
|
||||
(*argn) += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn], "-E") == 0)
|
||||
{
|
||||
g_test_case_insensitive = 1;
|
||||
get_fileinfo (args[*argn + 1], &ctx);
|
||||
g_test_case_insensitive = 0;
|
||||
update_val (ctx.file_exists, &ctx);
|
||||
(*argn) += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn], "-f") == 0)
|
||||
{
|
||||
get_fileinfo (args[*argn + 1], &ctx);
|
||||
/* FIXME: check for other types. */
|
||||
update_val (ctx.file_exists && ! ctx.file_info.dir, &ctx);
|
||||
(*argn) += 2;
|
||||
continue;
|
||||
}
|
||||
if (grub_strcmp (args[*argn], "-F") == 0)
|
||||
{
|
||||
g_test_case_insensitive = 1;
|
||||
get_fileinfo (args[*argn + 1], &ctx);
|
||||
g_test_case_insensitive = 0;
|
||||
/* FIXME: check for other types. */
|
||||
update_val (ctx.file_exists && ! ctx.file_info.dir, &ctx);
|
||||
(*argn) += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn], "-s") == 0)
|
||||
{
|
||||
grub_file_t file;
|
||||
file = grub_file_open (args[*argn + 1], GRUB_FILE_TYPE_GET_SIZE
|
||||
| GRUB_FILE_TYPE_NO_DECOMPRESS);
|
||||
update_val (file && (grub_file_size (file) != 0), &ctx);
|
||||
if (file)
|
||||
grub_file_close (file);
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
(*argn) += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* String tests. */
|
||||
if (grub_strcmp (args[*argn], "-n") == 0)
|
||||
{
|
||||
update_val (args[*argn + 1][0], &ctx);
|
||||
|
||||
(*argn) += 2;
|
||||
continue;
|
||||
}
|
||||
if (grub_strcmp (args[*argn], "-z") == 0)
|
||||
{
|
||||
update_val (! args[*argn + 1][0], &ctx);
|
||||
(*argn) += 2;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Special modifiers. */
|
||||
|
||||
/* End of expression. return to parent. */
|
||||
if (grub_strcmp (args[*argn], ")") == 0)
|
||||
{
|
||||
(*argn)++;
|
||||
return ctx.or || ctx.and;
|
||||
}
|
||||
/* Recursively invoke if parenthesis. */
|
||||
if (grub_strcmp (args[*argn], "(") == 0)
|
||||
{
|
||||
(*argn)++;
|
||||
update_val (test_parse (args, argn, argc), &ctx);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn], "!") == 0)
|
||||
{
|
||||
ctx.invert = ! ctx.invert;
|
||||
(*argn)++;
|
||||
continue;
|
||||
}
|
||||
if (grub_strcmp (args[*argn], "-a") == 0)
|
||||
{
|
||||
(*argn)++;
|
||||
continue;
|
||||
}
|
||||
if (grub_strcmp (args[*argn], "-o") == 0)
|
||||
{
|
||||
ctx.or = ctx.or || ctx.and;
|
||||
ctx.and = 1;
|
||||
(*argn)++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* No test found. Interpret if as just a string. */
|
||||
update_val (args[*argn][0], &ctx);
|
||||
(*argn)++;
|
||||
}
|
||||
return ctx.or || ctx.and;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_test (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
int argn = 0;
|
||||
|
||||
if (argc >= 1 && grub_strcmp (args[argc - 1], "]") == 0)
|
||||
argc--;
|
||||
|
||||
return test_parse (args, &argn, argc) ? GRUB_ERR_NONE
|
||||
: grub_error (GRUB_ERR_TEST_FAILURE, N_("false"));
|
||||
}
|
||||
|
||||
static grub_command_t cmd_1, cmd_2;
|
||||
|
||||
GRUB_MOD_INIT(test)
|
||||
{
|
||||
cmd_1 = grub_register_command ("[", grub_cmd_test,
|
||||
N_("EXPRESSION ]"), N_("Evaluate an expression."));
|
||||
cmd_1->flags |= GRUB_COMMAND_FLAG_EXTRACTOR;
|
||||
cmd_2 = grub_register_command ("test", grub_cmd_test,
|
||||
N_("EXPRESSION"), N_("Evaluate an expression."));
|
||||
cmd_2->flags |= GRUB_COMMAND_FLAG_EXTRACTOR;
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(test)
|
||||
{
|
||||
grub_unregister_command (cmd_1);
|
||||
grub_unregister_command (cmd_2);
|
||||
}
|
@@ -46,6 +46,7 @@
|
||||
#include <grub/dl.h>
|
||||
#include <grub/types.h>
|
||||
#include <grub/fshelp.h>
|
||||
#include <grub/ventoy.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -339,7 +340,7 @@ struct grub_ext2_data
|
||||
|
||||
static grub_dl_t my_mod;
|
||||
|
||||
|
||||
static int g_ventoy_block_count;
|
||||
|
||||
/* Check is a = b^x for some x. */
|
||||
static inline int
|
||||
@@ -499,6 +500,7 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||
start = grub_le_to_cpu16 (ext[i].start_hi);
|
||||
start = (start << 32) + grub_le_to_cpu32 (ext[i].start);
|
||||
|
||||
g_ventoy_block_count = (int)(grub_le_to_cpu16 (ext[i].len) - fileblock);
|
||||
ret = fileblock + start;
|
||||
}
|
||||
}
|
||||
@@ -1069,8 +1071,46 @@ grub_ext2_mtime (grub_device_t device, grub_int32_t *tm)
|
||||
|
||||
}
|
||||
|
||||
int grub_ext_get_file_chunk(grub_uint64_t part_start, grub_file_t file, ventoy_img_chunk_list *chunk_list)
|
||||
{
|
||||
int blocksize;
|
||||
int log2blocksize;
|
||||
grub_disk_t disk;
|
||||
grub_disk_addr_t i = 0;
|
||||
grub_disk_addr_t blockcnt;
|
||||
grub_disk_addr_t blknr;
|
||||
grub_fshelp_node_t node = NULL;
|
||||
|
||||
disk = file->device->disk;
|
||||
node = &(((struct grub_ext2_data *)file->data)->diropen);
|
||||
|
||||
log2blocksize = LOG2_EXT2_BLOCK_SIZE (node->data);
|
||||
blocksize = 1 << (log2blocksize + GRUB_DISK_SECTOR_BITS);
|
||||
blockcnt = (file->size + blocksize - 1) >> (log2blocksize + GRUB_DISK_SECTOR_BITS);
|
||||
|
||||
while (i < blockcnt)
|
||||
{
|
||||
g_ventoy_block_count = 1;
|
||||
blknr = grub_ext2_read_block(node, i);
|
||||
if (blknr == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
i += g_ventoy_block_count;
|
||||
blknr = blknr << log2blocksize;
|
||||
grub_disk_blocklist_read(chunk_list, blknr, g_ventoy_block_count * blocksize, disk->log_sector_size);
|
||||
}
|
||||
|
||||
for (i = 0; i < chunk_list->cur_chunk; i++)
|
||||
{
|
||||
chunk_list->chunk[i].disk_start_sector += part_start;
|
||||
chunk_list->chunk[i].disk_end_sector += part_start;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct grub_fs grub_ext2_fs =
|
||||
{
|
||||
.name = "ext2",
|
436
GRUB2/MOD_SRC/grub-2.04/grub-core/fs/fshelp.c
Normal file
@@ -0,0 +1,436 @@
|
||||
/* fshelp.c -- Filesystem helper functions */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2004,2005,2006,2007,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/err.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/fshelp.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
typedef int (*iterate_dir_func) (grub_fshelp_node_t dir,
|
||||
grub_fshelp_iterate_dir_hook_t hook,
|
||||
void *data);
|
||||
typedef grub_err_t (*lookup_file_func) (grub_fshelp_node_t dir,
|
||||
const char *name,
|
||||
grub_fshelp_node_t *foundnode,
|
||||
enum grub_fshelp_filetype *foundtype);
|
||||
typedef char *(*read_symlink_func) (grub_fshelp_node_t node);
|
||||
|
||||
struct stack_element {
|
||||
struct stack_element *parent;
|
||||
grub_fshelp_node_t node;
|
||||
enum grub_fshelp_filetype type;
|
||||
};
|
||||
|
||||
/* Context for grub_fshelp_find_file. */
|
||||
struct grub_fshelp_find_file_ctx
|
||||
{
|
||||
/* Inputs. */
|
||||
const char *path;
|
||||
grub_fshelp_node_t rootnode;
|
||||
|
||||
/* Global options. */
|
||||
int symlinknest;
|
||||
|
||||
/* Current file being traversed and its parents. */
|
||||
struct stack_element *currnode;
|
||||
};
|
||||
|
||||
/* Helper for find_file_iter. */
|
||||
static void
|
||||
free_node (grub_fshelp_node_t node, struct grub_fshelp_find_file_ctx *ctx)
|
||||
{
|
||||
if (node != ctx->rootnode)
|
||||
grub_free (node);
|
||||
}
|
||||
|
||||
static void
|
||||
pop_element (struct grub_fshelp_find_file_ctx *ctx)
|
||||
{
|
||||
struct stack_element *el;
|
||||
el = ctx->currnode;
|
||||
ctx->currnode = el->parent;
|
||||
free_node (el->node, ctx);
|
||||
grub_free (el);
|
||||
}
|
||||
|
||||
static void
|
||||
free_stack (struct grub_fshelp_find_file_ctx *ctx)
|
||||
{
|
||||
while (ctx->currnode)
|
||||
pop_element (ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
go_up_a_level (struct grub_fshelp_find_file_ctx *ctx)
|
||||
{
|
||||
if (!ctx->currnode->parent)
|
||||
return;
|
||||
pop_element (ctx);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
push_node (struct grub_fshelp_find_file_ctx *ctx, grub_fshelp_node_t node, enum grub_fshelp_filetype filetype)
|
||||
{
|
||||
struct stack_element *nst;
|
||||
nst = grub_malloc (sizeof (*nst));
|
||||
if (!nst)
|
||||
return grub_errno;
|
||||
nst->node = node;
|
||||
nst->type = filetype & ~GRUB_FSHELP_CASE_INSENSITIVE;
|
||||
nst->parent = ctx->currnode;
|
||||
ctx->currnode = nst;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
go_to_root (struct grub_fshelp_find_file_ctx *ctx)
|
||||
{
|
||||
free_stack (ctx);
|
||||
return push_node (ctx, ctx->rootnode, GRUB_FSHELP_DIR);
|
||||
}
|
||||
|
||||
struct grub_fshelp_find_file_iter_ctx
|
||||
{
|
||||
const char *name;
|
||||
grub_fshelp_node_t *foundnode;
|
||||
enum grub_fshelp_filetype *foundtype;
|
||||
};
|
||||
|
||||
int g_ventoy_case_insensitive = 0;
|
||||
|
||||
/* Helper for grub_fshelp_find_file. */
|
||||
static int
|
||||
find_file_iter (const char *filename, enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node, void *data)
|
||||
{
|
||||
struct grub_fshelp_find_file_iter_ctx *ctx = data;
|
||||
|
||||
if (g_ventoy_case_insensitive)
|
||||
{
|
||||
filetype |= GRUB_FSHELP_CASE_INSENSITIVE;
|
||||
}
|
||||
|
||||
if (filetype == GRUB_FSHELP_UNKNOWN ||
|
||||
((filetype & GRUB_FSHELP_CASE_INSENSITIVE)
|
||||
? grub_strcasecmp (ctx->name, filename)
|
||||
: grub_strcmp (ctx->name, filename)))
|
||||
{
|
||||
grub_free (node);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The node is found, stop iterating over the nodes. */
|
||||
*ctx->foundnode = node;
|
||||
*ctx->foundtype = filetype;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
directory_find_file (grub_fshelp_node_t node, const char *name, grub_fshelp_node_t *foundnode,
|
||||
enum grub_fshelp_filetype *foundtype, iterate_dir_func iterate_dir)
|
||||
{
|
||||
int found;
|
||||
struct grub_fshelp_find_file_iter_ctx ctx = {
|
||||
.foundnode = foundnode,
|
||||
.foundtype = foundtype,
|
||||
.name = name
|
||||
};
|
||||
found = iterate_dir (node, find_file_iter, &ctx);
|
||||
if (! found)
|
||||
{
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
}
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
find_file (char *currpath,
|
||||
iterate_dir_func iterate_dir, lookup_file_func lookup_file,
|
||||
read_symlink_func read_symlink,
|
||||
struct grub_fshelp_find_file_ctx *ctx)
|
||||
{
|
||||
char *name, *next;
|
||||
grub_err_t err;
|
||||
for (name = currpath; ; name = next)
|
||||
{
|
||||
char c;
|
||||
grub_fshelp_node_t foundnode = NULL;
|
||||
enum grub_fshelp_filetype foundtype = 0;
|
||||
|
||||
/* Remove all leading slashes. */
|
||||
while (*name == '/')
|
||||
name++;
|
||||
|
||||
/* Found the node! */
|
||||
if (! *name)
|
||||
return 0;
|
||||
|
||||
/* Extract the actual part from the pathname. */
|
||||
for (next = name; *next && *next != '/'; next++);
|
||||
|
||||
/* At this point it is expected that the current node is a
|
||||
directory, check if this is true. */
|
||||
if (ctx->currnode->type != GRUB_FSHELP_DIR)
|
||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
|
||||
|
||||
/* Don't rely on fs providing actual . in the listing. */
|
||||
if (next - name == 1 && name[0] == '.')
|
||||
continue;
|
||||
|
||||
/* Don't rely on fs providing actual .. in the listing. */
|
||||
if (next - name == 2 && name[0] == '.' && name[1] == '.')
|
||||
{
|
||||
go_up_a_level (ctx);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Iterate over the directory. */
|
||||
c = *next;
|
||||
*next = '\0';
|
||||
if (lookup_file)
|
||||
err = lookup_file (ctx->currnode->node, name, &foundnode, &foundtype);
|
||||
else
|
||||
err = directory_find_file (ctx->currnode->node, name, &foundnode, &foundtype, iterate_dir);
|
||||
*next = c;
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!foundnode)
|
||||
break;
|
||||
|
||||
push_node (ctx, foundnode, foundtype);
|
||||
|
||||
/* Read in the symlink and follow it. */
|
||||
if (ctx->currnode->type == GRUB_FSHELP_SYMLINK)
|
||||
{
|
||||
char *symlink;
|
||||
|
||||
/* Test if the symlink does not loop. */
|
||||
if (++ctx->symlinknest == 8)
|
||||
return grub_error (GRUB_ERR_SYMLINK_LOOP,
|
||||
N_("too deep nesting of symlinks"));
|
||||
|
||||
symlink = read_symlink (ctx->currnode->node);
|
||||
|
||||
if (!symlink)
|
||||
return grub_errno;
|
||||
|
||||
/* The symlink is an absolute path, go back to the root inode. */
|
||||
if (symlink[0] == '/')
|
||||
{
|
||||
err = go_to_root (ctx);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get from symlink to containing directory. */
|
||||
go_up_a_level (ctx);
|
||||
}
|
||||
|
||||
|
||||
/* Lookup the node the symlink points to. */
|
||||
find_file (symlink, iterate_dir, lookup_file, read_symlink, ctx);
|
||||
grub_free (symlink);
|
||||
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
}
|
||||
}
|
||||
|
||||
return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"),
|
||||
ctx->path);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_fshelp_find_file_real (const char *path, grub_fshelp_node_t rootnode,
|
||||
grub_fshelp_node_t *foundnode,
|
||||
iterate_dir_func iterate_dir,
|
||||
lookup_file_func lookup_file,
|
||||
read_symlink_func read_symlink,
|
||||
enum grub_fshelp_filetype expecttype)
|
||||
{
|
||||
struct grub_fshelp_find_file_ctx ctx = {
|
||||
.path = path,
|
||||
.rootnode = rootnode,
|
||||
.symlinknest = 0,
|
||||
.currnode = 0
|
||||
};
|
||||
grub_err_t err;
|
||||
enum grub_fshelp_filetype foundtype;
|
||||
char *duppath;
|
||||
|
||||
if (!path || path[0] != '/')
|
||||
{
|
||||
return grub_error (GRUB_ERR_BAD_FILENAME, N_("invalid file name `%s'"), path);
|
||||
}
|
||||
|
||||
err = go_to_root (&ctx);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
duppath = grub_strdup (path);
|
||||
if (!duppath)
|
||||
return grub_errno;
|
||||
err = find_file (duppath, iterate_dir, lookup_file, read_symlink, &ctx);
|
||||
grub_free (duppath);
|
||||
if (err)
|
||||
{
|
||||
free_stack (&ctx);
|
||||
return err;
|
||||
}
|
||||
|
||||
*foundnode = ctx.currnode->node;
|
||||
foundtype = ctx.currnode->type;
|
||||
/* Avoid the node being freed. */
|
||||
ctx.currnode->node = 0;
|
||||
free_stack (&ctx);
|
||||
|
||||
/* Check if the node that was found was of the expected type. */
|
||||
if (expecttype == GRUB_FSHELP_REG && foundtype != expecttype)
|
||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file"));
|
||||
else if (expecttype == GRUB_FSHELP_DIR && foundtype != expecttype)
|
||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Lookup the node PATH. The node ROOTNODE describes the root of the
|
||||
directory tree. The node found is returned in FOUNDNODE, which is
|
||||
either a ROOTNODE or a new malloc'ed node. ITERATE_DIR is used to
|
||||
iterate over all directory entries in the current node.
|
||||
READ_SYMLINK is used to read the symlink if a node is a symlink.
|
||||
EXPECTTYPE is the type node that is expected by the called, an
|
||||
error is generated if the node is not of the expected type. */
|
||||
grub_err_t
|
||||
grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode,
|
||||
grub_fshelp_node_t *foundnode,
|
||||
iterate_dir_func iterate_dir,
|
||||
read_symlink_func read_symlink,
|
||||
enum grub_fshelp_filetype expecttype)
|
||||
{
|
||||
return grub_fshelp_find_file_real (path, rootnode, foundnode,
|
||||
iterate_dir, NULL,
|
||||
read_symlink, expecttype);
|
||||
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_fshelp_find_file_lookup (const char *path, grub_fshelp_node_t rootnode,
|
||||
grub_fshelp_node_t *foundnode,
|
||||
lookup_file_func lookup_file,
|
||||
read_symlink_func read_symlink,
|
||||
enum grub_fshelp_filetype expecttype)
|
||||
{
|
||||
return grub_fshelp_find_file_real (path, rootnode, foundnode,
|
||||
NULL, lookup_file,
|
||||
read_symlink, expecttype);
|
||||
|
||||
}
|
||||
|
||||
/* Read LEN bytes from the file NODE on disk DISK into the buffer BUF,
|
||||
beginning with the block POS. READ_HOOK should be set before
|
||||
reading a block from the file. READ_HOOK_DATA is passed through as
|
||||
the DATA argument to READ_HOOK. GET_BLOCK is used to translate
|
||||
file blocks to disk blocks. The file is FILESIZE bytes big and the
|
||||
blocks have a size of LOG2BLOCKSIZE (in log2). */
|
||||
grub_ssize_t
|
||||
grub_fshelp_read_file (grub_disk_t disk, grub_fshelp_node_t node,
|
||||
grub_disk_read_hook_t read_hook, void *read_hook_data,
|
||||
grub_off_t pos, grub_size_t len, char *buf,
|
||||
grub_disk_addr_t (*get_block) (grub_fshelp_node_t node,
|
||||
grub_disk_addr_t block),
|
||||
grub_off_t filesize, int log2blocksize,
|
||||
grub_disk_addr_t blocks_start)
|
||||
{
|
||||
grub_disk_addr_t i, blockcnt;
|
||||
int blocksize = 1 << (log2blocksize + GRUB_DISK_SECTOR_BITS);
|
||||
|
||||
if (pos > filesize)
|
||||
{
|
||||
grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
N_("attempt to read past the end of file"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Adjust LEN so it we can't read past the end of the file. */
|
||||
if (pos + len > filesize)
|
||||
len = filesize - pos;
|
||||
|
||||
blockcnt = ((len + pos) + blocksize - 1) >> (log2blocksize + GRUB_DISK_SECTOR_BITS);
|
||||
|
||||
for (i = pos >> (log2blocksize + GRUB_DISK_SECTOR_BITS); i < blockcnt; i++)
|
||||
{
|
||||
grub_disk_addr_t blknr;
|
||||
int blockoff = pos & (blocksize - 1);
|
||||
int blockend = blocksize;
|
||||
|
||||
int skipfirst = 0;
|
||||
|
||||
blknr = get_block (node, i);
|
||||
if (grub_errno)
|
||||
return -1;
|
||||
|
||||
blknr = blknr << log2blocksize;
|
||||
|
||||
/* Last block. */
|
||||
if (i == blockcnt - 1)
|
||||
{
|
||||
blockend = (len + pos) & (blocksize - 1);
|
||||
|
||||
/* The last portion is exactly blocksize. */
|
||||
if (! blockend)
|
||||
blockend = blocksize;
|
||||
}
|
||||
|
||||
/* First block. */
|
||||
if (i == (pos >> (log2blocksize + GRUB_DISK_SECTOR_BITS)))
|
||||
{
|
||||
skipfirst = blockoff;
|
||||
blockend -= skipfirst;
|
||||
}
|
||||
|
||||
/* If the block number is 0 this block is not stored on disk but
|
||||
is zero filled instead. */
|
||||
if (blknr)
|
||||
{
|
||||
disk->read_hook = read_hook;
|
||||
disk->read_hook_data = read_hook_data;
|
||||
|
||||
grub_disk_read (disk, blknr + blocks_start, skipfirst,
|
||||
blockend, buf);
|
||||
disk->read_hook = 0;
|
||||
if (grub_errno)
|
||||
return -1;
|
||||
}
|
||||
else if (read_hook != (grub_disk_read_hook_t)grub_disk_blocklist_read)
|
||||
grub_memset (buf, 0, blockend);
|
||||
|
||||
buf += blocksize - skipfirst;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
@@ -32,6 +32,7 @@
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static int g_ventoy_no_joliet = 0;
|
||||
static grub_uint64_t g_ventoy_last_read_pos = 0;
|
||||
static grub_uint64_t g_ventoy_last_read_offset = 0;
|
||||
static grub_uint64_t g_ventoy_last_read_dirent_pos = 0;
|
||||
@@ -480,8 +481,10 @@ grub_iso9660_mount (grub_disk_t disk)
|
||||
(voldesc.escape[2] == 0x43) || /* UCS-2 Level 2. */
|
||||
(voldesc.escape[2] == 0x45))) /* UCS-2 Level 3. */
|
||||
{
|
||||
copy_voldesc = 1;
|
||||
data->joliet = 1;
|
||||
if (0 == g_ventoy_no_joliet) {
|
||||
copy_voldesc = 1;
|
||||
data->joliet = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (copy_voldesc)
|
||||
@@ -1108,6 +1111,11 @@ grub_iso9660_mtime (grub_device_t device, grub_int32_t *timebuf)
|
||||
return err;
|
||||
}
|
||||
|
||||
void grub_iso9660_set_nojoliet(int nojoliet)
|
||||
{
|
||||
g_ventoy_no_joliet = nojoliet;
|
||||
}
|
||||
|
||||
grub_uint64_t grub_iso9660_get_last_read_pos(grub_file_t file)
|
||||
{
|
||||
(void)file;
|
@@ -970,8 +970,6 @@ grub_xfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype,
|
||||
info.mtime = grub_be_to_cpu32 (node->inode.mtime.sec);
|
||||
}
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
if (!info.dir)
|
||||
info.size = node->inode.size;
|
||||
grub_free (node);
|
||||
return ctx->hook (filename, &info, ctx->hook_data);
|
||||
}
|
161
GRUB2/MOD_SRC/grub-2.04/grub-core/gfxmenu/gfxmenu.c
Normal file
@@ -0,0 +1,161 @@
|
||||
/* gfxmenu.c - Graphical menu interface controller. */
|
||||
/*
|
||||
* 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/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/video.h>
|
||||
#include <grub/gfxterm.h>
|
||||
#include <grub/bitmap.h>
|
||||
#include <grub/bitmap_scale.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/gfxwidgets.h>
|
||||
#include <grub/menu.h>
|
||||
#include <grub/menu_viewer.h>
|
||||
#include <grub/gfxmenu_model.h>
|
||||
#include <grub/gfxmenu_view.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
extern int g_ventoy_menu_refresh;
|
||||
|
||||
static grub_gfxmenu_view_t cached_view;
|
||||
|
||||
static void
|
||||
grub_gfxmenu_viewer_fini (void *data __attribute__ ((unused)))
|
||||
{
|
||||
}
|
||||
|
||||
/* FIXME: Previously 't' changed to text menu is it necessary? */
|
||||
static grub_err_t
|
||||
grub_gfxmenu_try (int entry, grub_menu_t menu, int nested)
|
||||
{
|
||||
int force_refresh = 0;
|
||||
grub_gfxmenu_view_t view = NULL;
|
||||
const char *theme_path;
|
||||
char *full_theme_path = 0;
|
||||
struct grub_menu_viewer *instance;
|
||||
grub_err_t err;
|
||||
struct grub_video_mode_info mode_info;
|
||||
|
||||
theme_path = grub_env_get ("theme");
|
||||
if (! theme_path)
|
||||
return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"),
|
||||
"theme");
|
||||
|
||||
err = grub_video_get_info (&mode_info);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
instance = grub_zalloc (sizeof (*instance));
|
||||
if (!instance)
|
||||
return grub_errno;
|
||||
|
||||
if (theme_path[0] != '/' && theme_path[0] != '(')
|
||||
{
|
||||
const char *prefix;
|
||||
prefix = grub_env_get ("prefix");
|
||||
full_theme_path = grub_xasprintf ("%s/themes/%s",
|
||||
prefix,
|
||||
theme_path);
|
||||
}
|
||||
|
||||
if (g_ventoy_menu_refresh)
|
||||
{
|
||||
g_ventoy_menu_refresh = 0;
|
||||
force_refresh = 1;
|
||||
}
|
||||
|
||||
if (force_refresh ||
|
||||
!cached_view || grub_strcmp (cached_view->theme_path,
|
||||
full_theme_path ? : theme_path) != 0
|
||||
|| cached_view->screen.width != mode_info.width
|
||||
|| cached_view->screen.height != mode_info.height)
|
||||
{
|
||||
grub_gfxmenu_view_destroy (cached_view);
|
||||
/* Create the view. */
|
||||
cached_view = grub_gfxmenu_view_new (full_theme_path ? : theme_path,
|
||||
mode_info.width,
|
||||
mode_info.height);
|
||||
}
|
||||
grub_free (full_theme_path);
|
||||
|
||||
if (! cached_view)
|
||||
{
|
||||
grub_free (instance);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
view = cached_view;
|
||||
|
||||
view->double_repaint = (mode_info.mode_type
|
||||
& GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED)
|
||||
&& !(mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP);
|
||||
view->selected = entry;
|
||||
view->menu = menu;
|
||||
view->nested = nested;
|
||||
view->first_timeout = -1;
|
||||
|
||||
grub_video_set_viewport (0, 0, mode_info.width, mode_info.height);
|
||||
if (view->double_repaint)
|
||||
{
|
||||
grub_video_swap_buffers ();
|
||||
grub_video_set_viewport (0, 0, mode_info.width, mode_info.height);
|
||||
}
|
||||
|
||||
grub_gfxmenu_view_draw (view);
|
||||
|
||||
instance->data = view;
|
||||
instance->set_chosen_entry = grub_gfxmenu_set_chosen_entry;
|
||||
instance->fini = grub_gfxmenu_viewer_fini;
|
||||
instance->print_timeout = grub_gfxmenu_print_timeout;
|
||||
instance->clear_timeout = grub_gfxmenu_clear_timeout;
|
||||
|
||||
grub_menu_register_viewer (instance);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
GRUB_MOD_INIT (gfxmenu)
|
||||
{
|
||||
struct grub_term_output *term;
|
||||
|
||||
FOR_ACTIVE_TERM_OUTPUTS(term)
|
||||
if (grub_gfxmenu_try_hook && term->fullscreen)
|
||||
{
|
||||
term->fullscreen ();
|
||||
break;
|
||||
}
|
||||
|
||||
grub_gfxmenu_try_hook = grub_gfxmenu_try;
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI (gfxmenu)
|
||||
{
|
||||
grub_gfxmenu_view_destroy (cached_view);
|
||||
grub_gfxmenu_try_hook = NULL;
|
||||
}
|
295
GRUB2/MOD_SRC/grub-2.04/grub-core/gfxmenu/gui_label.c
Normal file
@@ -0,0 +1,295 @@
|
||||
/* gui_label.c - GUI component to display a line of text. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 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/mm.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/gui.h>
|
||||
#include <grub/font.h>
|
||||
#include <grub/gui_string_util.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/color.h>
|
||||
#include <grub/env.h>
|
||||
|
||||
extern int g_ventoy_memdisk_mode;
|
||||
extern int g_ventoy_iso_raw;
|
||||
extern int g_ventoy_iso_uefi_drv;
|
||||
|
||||
static const char *align_options[] =
|
||||
{
|
||||
"left",
|
||||
"center",
|
||||
"right",
|
||||
0
|
||||
};
|
||||
|
||||
enum align_mode {
|
||||
align_left,
|
||||
align_center,
|
||||
align_right
|
||||
};
|
||||
|
||||
struct grub_gui_label
|
||||
{
|
||||
struct grub_gui_component comp;
|
||||
|
||||
grub_gui_container_t parent;
|
||||
grub_video_rect_t bounds;
|
||||
char *id;
|
||||
int visible;
|
||||
char *text;
|
||||
char *template;
|
||||
grub_font_t font;
|
||||
grub_video_rgba_color_t color;
|
||||
int value;
|
||||
enum align_mode align;
|
||||
};
|
||||
|
||||
typedef struct grub_gui_label *grub_gui_label_t;
|
||||
|
||||
static void
|
||||
label_destroy (void *vself)
|
||||
{
|
||||
grub_gui_label_t self = vself;
|
||||
grub_gfxmenu_timeout_unregister ((grub_gui_component_t) self);
|
||||
grub_free (self->text);
|
||||
grub_free (self->template);
|
||||
grub_free (self);
|
||||
}
|
||||
|
||||
static const char *
|
||||
label_get_id (void *vself)
|
||||
{
|
||||
grub_gui_label_t self = vself;
|
||||
return self->id;
|
||||
}
|
||||
|
||||
static int
|
||||
label_is_instance (void *vself __attribute__((unused)), const char *type)
|
||||
{
|
||||
return grub_strcmp (type, "component") == 0;
|
||||
}
|
||||
|
||||
static void
|
||||
label_paint (void *vself, const grub_video_rect_t *region)
|
||||
{
|
||||
grub_gui_label_t self = vself;
|
||||
|
||||
if (! self->visible)
|
||||
return;
|
||||
|
||||
if (!grub_video_have_common_points (region, &self->bounds))
|
||||
return;
|
||||
|
||||
/* Calculate the starting x coordinate. */
|
||||
int left_x;
|
||||
if (self->align == align_left)
|
||||
left_x = 0;
|
||||
else if (self->align == align_center)
|
||||
left_x = (self->bounds.width
|
||||
- grub_font_get_string_width (self->font, self->text)) / 2;
|
||||
else if (self->align == align_right)
|
||||
left_x = (self->bounds.width
|
||||
- grub_font_get_string_width (self->font, self->text));
|
||||
else
|
||||
return; /* Invalid alignment. */
|
||||
|
||||
if (left_x < 0 || left_x > (int) self->bounds.width)
|
||||
left_x = 0;
|
||||
|
||||
grub_video_rect_t vpsave;
|
||||
grub_gui_set_viewport (&self->bounds, &vpsave);
|
||||
grub_font_draw_string (self->text,
|
||||
self->font,
|
||||
grub_video_map_rgba_color (self->color),
|
||||
left_x,
|
||||
grub_font_get_ascent (self->font));
|
||||
grub_gui_restore_viewport (&vpsave);
|
||||
}
|
||||
|
||||
static void
|
||||
label_set_parent (void *vself, grub_gui_container_t parent)
|
||||
{
|
||||
grub_gui_label_t self = vself;
|
||||
self->parent = parent;
|
||||
}
|
||||
|
||||
static grub_gui_container_t
|
||||
label_get_parent (void *vself)
|
||||
{
|
||||
grub_gui_label_t self = vself;
|
||||
return self->parent;
|
||||
}
|
||||
|
||||
static void
|
||||
label_set_bounds (void *vself, const grub_video_rect_t *bounds)
|
||||
{
|
||||
grub_gui_label_t self = vself;
|
||||
self->bounds = *bounds;
|
||||
}
|
||||
|
||||
static void
|
||||
label_get_bounds (void *vself, grub_video_rect_t *bounds)
|
||||
{
|
||||
grub_gui_label_t self = vself;
|
||||
*bounds = self->bounds;
|
||||
}
|
||||
|
||||
static void
|
||||
label_get_minimal_size (void *vself, unsigned *width, unsigned *height)
|
||||
{
|
||||
grub_gui_label_t self = vself;
|
||||
*width = grub_font_get_string_width (self->font, self->text);
|
||||
*height = (grub_font_get_ascent (self->font)
|
||||
+ grub_font_get_descent (self->font));
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
|
||||
|
||||
static void
|
||||
label_set_state (void *vself, int visible, int start __attribute__ ((unused)),
|
||||
int current, int end __attribute__ ((unused)))
|
||||
{
|
||||
grub_gui_label_t self = vself;
|
||||
self->value = -current;
|
||||
self->visible = visible;
|
||||
grub_free (self->text);
|
||||
self->text = grub_xasprintf (self->template ? : "%d", self->value);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
label_set_property (void *vself, const char *name, const char *value)
|
||||
{
|
||||
grub_gui_label_t self = vself;
|
||||
if (grub_strcmp (name, "text") == 0)
|
||||
{
|
||||
grub_free (self->text);
|
||||
grub_free (self->template);
|
||||
if (! value)
|
||||
{
|
||||
self->template = NULL;
|
||||
self->text = grub_strdup ("");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (grub_strcmp (value, "@KEYMAP_LONG@") == 0)
|
||||
value = _("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.");
|
||||
else if (grub_strcmp (value, "@KEYMAP_MIDDLE@") == 0)
|
||||
value = _("Press enter to boot the selected OS, "
|
||||
"`e' to edit the commands before booting "
|
||||
"or `c' for a command-line.");
|
||||
else if (grub_strcmp (value, "@KEYMAP_SHORT@") == 0)
|
||||
value = _("enter: boot, `e': options, `c': cmd-line");
|
||||
/* FIXME: Add more templates here if needed. */
|
||||
|
||||
else if (grub_strcmp (value, "@VTOY_MEM_DISK@") == 0) {
|
||||
value = g_ventoy_memdisk_mode ? grub_env_get("VTOY_MEM_DISK_STR") : " ";
|
||||
}
|
||||
else if (grub_strcmp (value, "@VTOY_ISO_RAW@") == 0) {
|
||||
value = g_ventoy_iso_raw ? grub_env_get("VTOY_ISO_RAW_STR") : " ";
|
||||
}
|
||||
else if (grub_strcmp (value, "@VTOY_ISO_UEFI_DRV@") == 0) {
|
||||
value = g_ventoy_iso_uefi_drv ? grub_env_get("VTOY_ISO_UEFI_DRV_STR") : " ";
|
||||
}
|
||||
else if (grub_strcmp (value, "@VTOY_HOTKEY_TIP@") == 0) {
|
||||
value = grub_env_get("VTOY_HOTKEY_TIP");
|
||||
if (value == NULL) {
|
||||
value = _(" ");
|
||||
}
|
||||
}
|
||||
|
||||
self->template = grub_strdup (value);
|
||||
self->text = grub_xasprintf (value, self->value);
|
||||
}
|
||||
}
|
||||
else if (grub_strcmp (name, "font") == 0)
|
||||
{
|
||||
self->font = grub_font_get (value);
|
||||
}
|
||||
else if (grub_strcmp (name, "color") == 0)
|
||||
{
|
||||
grub_video_parse_color (value, &self->color);
|
||||
}
|
||||
else if (grub_strcmp (name, "align") == 0)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; align_options[i]; i++)
|
||||
{
|
||||
if (grub_strcmp (align_options[i], value) == 0)
|
||||
{
|
||||
self->align = i; /* Set the alignment mode. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (grub_strcmp (name, "visible") == 0)
|
||||
{
|
||||
self->visible = grub_strcmp (value, "false") != 0;
|
||||
}
|
||||
else if (grub_strcmp (name, "id") == 0)
|
||||
{
|
||||
grub_gfxmenu_timeout_unregister ((grub_gui_component_t) self);
|
||||
grub_free (self->id);
|
||||
if (value)
|
||||
self->id = grub_strdup (value);
|
||||
else
|
||||
self->id = 0;
|
||||
if (self->id && grub_strcmp (self->id, GRUB_GFXMENU_TIMEOUT_COMPONENT_ID)
|
||||
== 0)
|
||||
grub_gfxmenu_timeout_register ((grub_gui_component_t) self,
|
||||
label_set_state);
|
||||
}
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic error "-Wformat-nonliteral"
|
||||
|
||||
static struct grub_gui_component_ops label_ops =
|
||||
{
|
||||
.destroy = label_destroy,
|
||||
.get_id = label_get_id,
|
||||
.is_instance = label_is_instance,
|
||||
.paint = label_paint,
|
||||
.set_parent = label_set_parent,
|
||||
.get_parent = label_get_parent,
|
||||
.set_bounds = label_set_bounds,
|
||||
.get_bounds = label_get_bounds,
|
||||
.get_minimal_size = label_get_minimal_size,
|
||||
.set_property = label_set_property
|
||||
};
|
||||
|
||||
grub_gui_component_t
|
||||
grub_gui_label_new (void)
|
||||
{
|
||||
grub_gui_label_t label;
|
||||
label = grub_zalloc (sizeof (*label));
|
||||
if (! label)
|
||||
return 0;
|
||||
label->comp.ops = &label_ops;
|
||||
label->visible = 1;
|
||||
label->text = grub_strdup ("");
|
||||
label->font = grub_font_get ("Unknown Regular 16");
|
||||
label->color.red = 0;
|
||||
label->color.green = 0;
|
||||
label->color.blue = 0;
|
||||
label->color.alpha = 255;
|
||||
label->align = align_left;
|
||||
return (grub_gui_component_t) label;
|
||||
}
|
@@ -27,7 +27,7 @@
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/ventoy.h>
|
||||
|
||||
#define GRUB_CACHE_TIMEOUT 2
|
||||
#define GRUB_CACHE_TIMEOUT 10
|
||||
|
||||
/* The last time the disk was used. */
|
||||
static grub_uint64_t grub_last_time = 0;
|
||||
@@ -412,16 +412,23 @@ grub_disk_read_small (grub_disk_t disk, grub_disk_addr_t sector,
|
||||
grub_err_t grub_disk_blocklist_read(void *chunklist, grub_uint64_t sector,
|
||||
grub_uint64_t size, grub_uint32_t log_sector_size)
|
||||
{
|
||||
grub_uint64_t sizeshift;
|
||||
ventoy_img_chunk *last_chunk = NULL;
|
||||
ventoy_img_chunk *new_chunk = NULL;
|
||||
ventoy_img_chunk_list *chunk_list = (ventoy_img_chunk_list *)chunklist;
|
||||
|
||||
sizeshift = (size >> log_sector_size);
|
||||
if (sizeshift == 0)
|
||||
{
|
||||
sizeshift = 1;
|
||||
}
|
||||
|
||||
if (chunk_list->cur_chunk == 0)
|
||||
{
|
||||
chunk_list->chunk[0].img_start_sector = 0;
|
||||
chunk_list->chunk[0].img_end_sector = (size >> 11) - 1;
|
||||
chunk_list->chunk[0].disk_start_sector = sector;
|
||||
chunk_list->chunk[0].disk_end_sector = sector + (size >> log_sector_size) - 1;
|
||||
chunk_list->chunk[0].disk_end_sector = sector + sizeshift - 1;
|
||||
chunk_list->cur_chunk = 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -430,7 +437,7 @@ grub_err_t grub_disk_blocklist_read(void *chunklist, grub_uint64_t sector,
|
||||
if (last_chunk->disk_end_sector + 1 == sector)
|
||||
{
|
||||
last_chunk->img_end_sector += (size >> 11);
|
||||
last_chunk->disk_end_sector += (size >> log_sector_size);
|
||||
last_chunk->disk_end_sector += sizeshift;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -452,7 +459,7 @@ grub_err_t grub_disk_blocklist_read(void *chunklist, grub_uint64_t sector,
|
||||
new_chunk->img_start_sector = last_chunk->img_end_sector + 1;
|
||||
new_chunk->img_end_sector = new_chunk->img_start_sector + (size >> 11) - 1;
|
||||
new_chunk->disk_start_sector = sector;
|
||||
new_chunk->disk_end_sector = sector + (size >> log_sector_size) - 1;
|
||||
new_chunk->disk_end_sector = sector + sizeshift - 1;
|
||||
|
||||
chunk_list->cur_chunk++;
|
||||
|
@@ -83,6 +83,29 @@ grub_file_t grub_memfile_open(const char *name)
|
||||
return file;
|
||||
}
|
||||
|
||||
int ventoy_check_file_exist(const char * fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
grub_file_t file;
|
||||
char fullpath[256] = {0};
|
||||
|
||||
va_start (ap, fmt);
|
||||
grub_vsnprintf(fullpath, 255, fmt, ap);
|
||||
va_end (ap);
|
||||
|
||||
file = grub_file_open(fullpath, GRUB_FILE_TYPE_NONE);
|
||||
if (!file)
|
||||
{
|
||||
grub_errno = 0;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_file_close(file);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
grub_file_t
|
||||
grub_file_open (const char *name, enum grub_file_type type)
|
||||
{
|
@@ -260,6 +260,45 @@ reclaim_module_space (void)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef GRUB_MACHINE_EFI
|
||||
static int ventoy_legacy_limit_workaround(void)
|
||||
{
|
||||
grub_file_t file;
|
||||
char *pos, *root;
|
||||
char buf[128];
|
||||
|
||||
root = grub_strdup(grub_env_get("root"));
|
||||
if (!root)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
pos = grub_strchr(root, ',');
|
||||
if (pos) *pos = 0;
|
||||
|
||||
grub_snprintf(buf, sizeof(buf), "(%s,1)/ventoy/ventoy.disk.img.xz", root);
|
||||
file = grub_file_open(buf, GRUB_FILE_TYPE_NONE);
|
||||
if (file)
|
||||
{
|
||||
pos = grub_malloc(file->size);
|
||||
if (pos)
|
||||
{
|
||||
grub_file_read(file, pos, file->size);
|
||||
grub_snprintf(buf, sizeof(buf), "loopback ventoydisk mem:0x%lx:size:%lu",
|
||||
(unsigned long)pos, (unsigned long)file->size);
|
||||
|
||||
grub_parser_execute(buf);
|
||||
grub_env_set("prefix", "(ventoydisk)/grub");
|
||||
}
|
||||
|
||||
grub_file_close(file);
|
||||
}
|
||||
|
||||
grub_free(root);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* The main routine. */
|
||||
void __attribute__ ((noreturn))
|
||||
grub_main (void)
|
||||
@@ -293,6 +332,12 @@ grub_main (void)
|
||||
grub_env_export ("root");
|
||||
grub_env_export ("prefix");
|
||||
|
||||
#ifndef GRUB_MACHINE_EFI
|
||||
if (0 == ventoy_check_file_exist("%s/grub.cfg", grub_env_get("prefix"))) {
|
||||
ventoy_legacy_limit_workaround();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Reclaim space used for modules. */
|
||||
reclaim_module_space ();
|
||||
|
214
GRUB2/MOD_SRC/grub-2.04/grub-core/normal/context.c
Normal file
@@ -0,0 +1,214 @@
|
||||
/* env.c - Environment variables */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 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/env.h>
|
||||
#include <grub/env_private.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
struct menu_pointer
|
||||
{
|
||||
grub_menu_t menu;
|
||||
struct menu_pointer *prev;
|
||||
};
|
||||
|
||||
static struct menu_pointer initial_menu;
|
||||
static struct menu_pointer *current_menu = &initial_menu;
|
||||
|
||||
void
|
||||
grub_env_unset_menu (void)
|
||||
{
|
||||
current_menu->menu = NULL;
|
||||
}
|
||||
|
||||
grub_menu_t
|
||||
grub_env_get_menu (void)
|
||||
{
|
||||
return current_menu->menu;
|
||||
}
|
||||
|
||||
void
|
||||
grub_env_set_menu (grub_menu_t nmenu)
|
||||
{
|
||||
current_menu->menu = nmenu;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_env_new_context (int export_all)
|
||||
{
|
||||
struct grub_env_context *context;
|
||||
int i;
|
||||
struct menu_pointer *menu;
|
||||
|
||||
context = grub_zalloc (sizeof (*context));
|
||||
if (! context)
|
||||
return grub_errno;
|
||||
menu = grub_zalloc (sizeof (*menu));
|
||||
if (! menu)
|
||||
{
|
||||
grub_free (context);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
context->prev = grub_current_context;
|
||||
grub_current_context = context;
|
||||
|
||||
menu->prev = current_menu;
|
||||
current_menu = menu;
|
||||
|
||||
/* Copy exported variables. */
|
||||
for (i = 0; i < HASHSZ; i++)
|
||||
{
|
||||
struct grub_env_var *var;
|
||||
|
||||
for (var = context->prev->vars[i]; var; var = var->next)
|
||||
if (var->global || export_all)
|
||||
{
|
||||
if (grub_env_set (var->name, var->value) != GRUB_ERR_NONE)
|
||||
{
|
||||
grub_env_context_close ();
|
||||
return grub_errno;
|
||||
}
|
||||
grub_env_export (var->name);
|
||||
grub_register_variable_hook (var->name, var->read_hook, var->write_hook);
|
||||
}
|
||||
}
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_env_context_open (void)
|
||||
{
|
||||
return grub_env_new_context (grub_env_get("ventoy_new_context") ? 0 : 1);
|
||||
}
|
||||
|
||||
int grub_extractor_level = 0;
|
||||
|
||||
grub_err_t
|
||||
grub_env_extractor_open (int source)
|
||||
{
|
||||
grub_extractor_level++;
|
||||
return grub_env_new_context (source);
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_env_context_close (void)
|
||||
{
|
||||
struct grub_env_context *context;
|
||||
int i;
|
||||
struct menu_pointer *menu;
|
||||
|
||||
if (! grub_current_context->prev)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"cannot close the initial context");
|
||||
|
||||
/* Free the variables associated with this context. */
|
||||
for (i = 0; i < HASHSZ; i++)
|
||||
{
|
||||
struct grub_env_var *p, *q;
|
||||
|
||||
for (p = grub_current_context->vars[i]; p; p = q)
|
||||
{
|
||||
q = p->next;
|
||||
grub_free (p->name);
|
||||
grub_free (p->value);
|
||||
grub_free (p);
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore the previous context. */
|
||||
context = grub_current_context->prev;
|
||||
grub_free (grub_current_context);
|
||||
grub_current_context = context;
|
||||
|
||||
menu = current_menu->prev;
|
||||
if (current_menu->menu)
|
||||
grub_normal_free_menu (current_menu->menu);
|
||||
grub_free (current_menu);
|
||||
current_menu = menu;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_env_extractor_close (int source)
|
||||
{
|
||||
grub_menu_t menu = NULL;
|
||||
grub_menu_entry_t *last;
|
||||
grub_err_t err;
|
||||
|
||||
if (source)
|
||||
{
|
||||
menu = grub_env_get_menu ();
|
||||
grub_env_unset_menu ();
|
||||
}
|
||||
err = grub_env_context_close ();
|
||||
|
||||
if (source && menu)
|
||||
{
|
||||
grub_menu_t menu2;
|
||||
menu2 = grub_env_get_menu ();
|
||||
|
||||
last = &menu2->entry_list;
|
||||
while (*last)
|
||||
last = &(*last)->next;
|
||||
|
||||
*last = menu->entry_list;
|
||||
menu2->size += menu->size;
|
||||
}
|
||||
|
||||
grub_extractor_level--;
|
||||
return err;
|
||||
}
|
||||
|
||||
static grub_command_t export_cmd;
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_export (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (argc < 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
N_("one argument expected"));
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
grub_env_export (args[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
grub_context_init (void)
|
||||
{
|
||||
export_cmd = grub_register_command ("export", grub_cmd_export,
|
||||
N_("ENVVAR [ENVVAR] ..."),
|
||||
N_("Export variables."));
|
||||
}
|
||||
|
||||
void
|
||||
grub_context_fini (void)
|
||||
{
|
||||
grub_unregister_command (export_cmd);
|
||||
}
|
@@ -38,7 +38,10 @@ int g_ventoy_menu_refresh = 0;
|
||||
int g_ventoy_memdisk_mode = 0;
|
||||
int g_ventoy_iso_raw = 0;
|
||||
int g_ventoy_iso_uefi_drv = 0;
|
||||
int g_ventoy_last_entry = 0;
|
||||
int g_ventoy_last_entry = -1;
|
||||
int g_ventoy_suppress_esc = 0;
|
||||
int g_ventoy_menu_esc = 0;
|
||||
int g_ventoy_fn_mutex = 0;
|
||||
|
||||
/* Time to delay after displaying an error message about a default/fallback
|
||||
entry failing to boot. */
|
||||
@@ -590,8 +593,10 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
|
||||
enum timeout_style timeout_style;
|
||||
|
||||
default_entry = get_entry_number (menu, "default");
|
||||
|
||||
if (g_ventoy_last_entry >= 0 && g_ventoy_last_entry < menu->size) {
|
||||
|
||||
if (g_ventoy_suppress_esc)
|
||||
default_entry = 1;
|
||||
else if (g_ventoy_last_entry >= 0 && g_ventoy_last_entry < menu->size) {
|
||||
default_entry = g_ventoy_last_entry;
|
||||
}
|
||||
/* If DEFAULT_ENTRY is not within the menu entries, fall back to
|
||||
@@ -771,12 +776,12 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
|
||||
case '\r':
|
||||
// case GRUB_TERM_KEY_RIGHT:
|
||||
case GRUB_TERM_CTRL | 'f':
|
||||
menu_fini ();
|
||||
menu_fini ();
|
||||
*auto_boot = 0;
|
||||
return current_entry;
|
||||
return current_entry;
|
||||
|
||||
case GRUB_TERM_ESC:
|
||||
if (nested)
|
||||
if (nested && 0 == g_ventoy_suppress_esc)
|
||||
{
|
||||
menu_fini ();
|
||||
return -1;
|
||||
@@ -798,48 +803,66 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
|
||||
goto refresh;
|
||||
|
||||
case GRUB_TERM_KEY_F2:
|
||||
cmdstr = grub_env_get("VTOY_F2_CMD");
|
||||
if (cmdstr)
|
||||
{
|
||||
menu_fini ();
|
||||
grub_script_execute_sourcecode(cmdstr);
|
||||
goto refresh;
|
||||
if (0 == g_ventoy_fn_mutex) {
|
||||
cmdstr = grub_env_get("VTOY_F2_CMD");
|
||||
if (cmdstr)
|
||||
{
|
||||
menu_fini ();
|
||||
g_ventoy_fn_mutex = 1;
|
||||
grub_script_execute_sourcecode(cmdstr);
|
||||
g_ventoy_fn_mutex = 0;
|
||||
goto refresh;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GRUB_TERM_KEY_F3:
|
||||
cmdstr = grub_env_get("VTOY_F3_CMD");
|
||||
if (cmdstr)
|
||||
{
|
||||
menu_fini ();
|
||||
grub_script_execute_sourcecode(cmdstr);
|
||||
goto refresh;
|
||||
if (0 == g_ventoy_fn_mutex) {
|
||||
cmdstr = grub_env_get("VTOY_F3_CMD");
|
||||
if (cmdstr)
|
||||
{
|
||||
menu_fini ();
|
||||
grub_script_execute_sourcecode(cmdstr);
|
||||
goto refresh;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GRUB_TERM_KEY_F4:
|
||||
cmdstr = grub_env_get("VTOY_F4_CMD");
|
||||
if (cmdstr)
|
||||
{
|
||||
menu_fini ();
|
||||
grub_script_execute_sourcecode(cmdstr);
|
||||
goto refresh;
|
||||
if (0 == g_ventoy_fn_mutex) {
|
||||
cmdstr = grub_env_get("VTOY_F4_CMD");
|
||||
if (cmdstr)
|
||||
{
|
||||
menu_fini ();
|
||||
g_ventoy_fn_mutex = 1;
|
||||
grub_script_execute_sourcecode(cmdstr);
|
||||
g_ventoy_fn_mutex = 0;
|
||||
goto refresh;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GRUB_TERM_KEY_F5:
|
||||
cmdstr = grub_env_get("VTOY_F5_CMD");
|
||||
if (cmdstr)
|
||||
{
|
||||
menu_fini ();
|
||||
grub_script_execute_sourcecode(cmdstr);
|
||||
goto refresh;
|
||||
if (0 == g_ventoy_fn_mutex) {
|
||||
cmdstr = grub_env_get("VTOY_F5_CMD");
|
||||
if (cmdstr)
|
||||
{
|
||||
menu_fini ();
|
||||
g_ventoy_fn_mutex = 1;
|
||||
grub_script_execute_sourcecode(cmdstr);
|
||||
g_ventoy_fn_mutex = 0;
|
||||
goto refresh;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GRUB_TERM_KEY_F6:
|
||||
cmdstr = grub_env_get("VTOY_F6_CMD");
|
||||
if (cmdstr)
|
||||
{
|
||||
menu_fini ();
|
||||
grub_script_execute_sourcecode(cmdstr);
|
||||
goto refresh;
|
||||
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:
|
||||
@@ -950,11 +973,16 @@ show_menu (grub_menu_t menu, int nested, int autobooted)
|
||||
break;
|
||||
|
||||
g_ventoy_last_entry = boot_entry;
|
||||
if (g_ventoy_menu_esc)
|
||||
break;
|
||||
|
||||
e = grub_menu_get_entry (menu, boot_entry);
|
||||
if (! e)
|
||||
continue; /* Menu is empty. */
|
||||
|
||||
if (2 == e->argc && e->args && e->args[1] && grub_strncmp(e->args[1], "VTOY_RET", 8) == 0)
|
||||
break;
|
||||
|
||||
grub_cls ();
|
||||
|
||||
if (auto_boot)
|
605
GRUB2/MOD_SRC/grub-2.04/grub-core/normal/menu_text.c
Normal file
@@ -0,0 +1,605 @@
|
||||
/* menu_text.c - Basic text menu implementation. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2003,2004,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/normal.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/loader.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/menu_viewer.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/charset.h>
|
||||
|
||||
static grub_uint8_t grub_color_menu_normal;
|
||||
static grub_uint8_t grub_color_menu_highlight;
|
||||
|
||||
struct menu_viewer_data
|
||||
{
|
||||
int first, offset;
|
||||
struct grub_term_screen_geometry geo;
|
||||
enum {
|
||||
TIMEOUT_UNKNOWN,
|
||||
TIMEOUT_NORMAL,
|
||||
TIMEOUT_TERSE,
|
||||
TIMEOUT_TERSE_NO_MARGIN
|
||||
} timeout_msg;
|
||||
grub_menu_t menu;
|
||||
struct grub_term_output *term;
|
||||
};
|
||||
|
||||
static inline int
|
||||
grub_term_cursor_x (const struct grub_term_screen_geometry *geo)
|
||||
{
|
||||
return (geo->first_entry_x + geo->entry_width);
|
||||
}
|
||||
|
||||
grub_size_t
|
||||
grub_getstringwidth (grub_uint32_t * str, const grub_uint32_t * last_position,
|
||||
struct grub_term_output *term)
|
||||
{
|
||||
grub_ssize_t width = 0;
|
||||
|
||||
while (str < last_position)
|
||||
{
|
||||
struct grub_unicode_glyph glyph;
|
||||
glyph.ncomb = 0;
|
||||
str += grub_unicode_aglomerate_comb (str, last_position - str, &glyph);
|
||||
width += grub_term_getcharwidth (term, &glyph);
|
||||
grub_unicode_destroy_glyph (&glyph);
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
static int
|
||||
grub_print_message_indented_real (const char *msg, int margin_left,
|
||||
int margin_right,
|
||||
struct grub_term_output *term, int dry_run)
|
||||
{
|
||||
grub_uint32_t *unicode_msg;
|
||||
grub_uint32_t *last_position;
|
||||
grub_size_t msg_len = grub_strlen (msg) + 2;
|
||||
int ret = 0;
|
||||
|
||||
unicode_msg = grub_malloc (msg_len * sizeof (grub_uint32_t));
|
||||
|
||||
if (!unicode_msg)
|
||||
return 0;
|
||||
|
||||
msg_len = grub_utf8_to_ucs4 (unicode_msg, msg_len,
|
||||
(grub_uint8_t *) msg, -1, 0);
|
||||
|
||||
last_position = unicode_msg + msg_len;
|
||||
*last_position = 0;
|
||||
|
||||
if (dry_run)
|
||||
ret = grub_ucs4_count_lines (unicode_msg, last_position, margin_left,
|
||||
margin_right, term);
|
||||
else
|
||||
grub_print_ucs4_menu (unicode_msg, last_position, margin_left,
|
||||
margin_right, term, 0, -1, 0, 0);
|
||||
|
||||
grub_free (unicode_msg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
grub_print_message_indented (const char *msg, int margin_left, int margin_right,
|
||||
struct grub_term_output *term)
|
||||
{
|
||||
grub_print_message_indented_real (msg, margin_left, margin_right, term, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_border (struct grub_term_output *term, const struct grub_term_screen_geometry *geo)
|
||||
{
|
||||
int i;
|
||||
|
||||
grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL);
|
||||
|
||||
grub_term_gotoxy (term, (struct grub_term_coordinate) { geo->first_entry_x - 1,
|
||||
geo->first_entry_y - 1 });
|
||||
grub_putcode (GRUB_UNICODE_CORNER_UL, term);
|
||||
for (i = 0; i < geo->entry_width + 1; i++)
|
||||
grub_putcode (GRUB_UNICODE_HLINE, term);
|
||||
grub_putcode (GRUB_UNICODE_CORNER_UR, term);
|
||||
|
||||
for (i = 0; i < geo->num_entries; i++)
|
||||
{
|
||||
grub_term_gotoxy (term, (struct grub_term_coordinate) { geo->first_entry_x - 1,
|
||||
geo->first_entry_y + i });
|
||||
grub_putcode (GRUB_UNICODE_VLINE, term);
|
||||
grub_term_gotoxy (term,
|
||||
(struct grub_term_coordinate) { geo->first_entry_x + geo->entry_width + 1,
|
||||
geo->first_entry_y + i });
|
||||
grub_putcode (GRUB_UNICODE_VLINE, term);
|
||||
}
|
||||
|
||||
grub_term_gotoxy (term,
|
||||
(struct grub_term_coordinate) { geo->first_entry_x - 1,
|
||||
geo->first_entry_y - 1 + geo->num_entries + 1 });
|
||||
grub_putcode (GRUB_UNICODE_CORNER_LL, term);
|
||||
for (i = 0; i < geo->entry_width + 1; i++)
|
||||
grub_putcode (GRUB_UNICODE_HLINE, term);
|
||||
grub_putcode (GRUB_UNICODE_CORNER_LR, term);
|
||||
|
||||
grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL);
|
||||
|
||||
grub_term_gotoxy (term,
|
||||
(struct grub_term_coordinate) { geo->first_entry_x - 1,
|
||||
(geo->first_entry_y - 1 + geo->num_entries
|
||||
+ GRUB_TERM_MARGIN + 1) });
|
||||
}
|
||||
|
||||
static int
|
||||
print_message (int nested, int edit, struct grub_term_output *term, int dry_run)
|
||||
{
|
||||
int ret = 0;
|
||||
grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL);
|
||||
|
||||
if (edit)
|
||||
{
|
||||
ret += grub_print_message_indented_real (_("Minimum Emacs-like screen editing is \
|
||||
supported. TAB lists completions. Press Ctrl-x or F10 to boot, Ctrl-c or F2 for a \
|
||||
command-line or ESC to discard edits and return to the GRUB menu."),
|
||||
STANDARD_MARGIN, STANDARD_MARGIN,
|
||||
term, dry_run);
|
||||
}
|
||||
else
|
||||
{
|
||||
char *msg_translated;
|
||||
|
||||
msg_translated = grub_xasprintf (_("Use the %C and %C keys to select which "
|
||||
"entry is highlighted."),
|
||||
GRUB_UNICODE_UPARROW,
|
||||
GRUB_UNICODE_DOWNARROW);
|
||||
if (!msg_translated)
|
||||
return 0;
|
||||
ret += grub_print_message_indented_real (msg_translated, STANDARD_MARGIN,
|
||||
STANDARD_MARGIN, term, dry_run);
|
||||
|
||||
grub_free (msg_translated);
|
||||
|
||||
if (nested)
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
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("\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);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
print_entry (int y, int highlight, grub_menu_entry_t entry,
|
||||
const struct menu_viewer_data *data)
|
||||
{
|
||||
const char *title;
|
||||
grub_size_t title_len;
|
||||
grub_ssize_t len;
|
||||
grub_uint32_t *unicode_title;
|
||||
grub_ssize_t i;
|
||||
grub_uint8_t old_color_normal, old_color_highlight;
|
||||
|
||||
title = entry ? entry->title : "";
|
||||
title_len = grub_strlen (title);
|
||||
unicode_title = grub_malloc (title_len * sizeof (*unicode_title));
|
||||
if (! unicode_title)
|
||||
/* XXX How to show this error? */
|
||||
return;
|
||||
|
||||
len = grub_utf8_to_ucs4 (unicode_title, title_len,
|
||||
(grub_uint8_t *) title, -1, 0);
|
||||
if (len < 0)
|
||||
{
|
||||
/* It is an invalid sequence. */
|
||||
grub_free (unicode_title);
|
||||
return;
|
||||
}
|
||||
|
||||
old_color_normal = grub_term_normal_color;
|
||||
old_color_highlight = grub_term_highlight_color;
|
||||
grub_term_normal_color = grub_color_menu_normal;
|
||||
grub_term_highlight_color = grub_color_menu_highlight;
|
||||
grub_term_setcolorstate (data->term, highlight
|
||||
? GRUB_TERM_COLOR_HIGHLIGHT
|
||||
: GRUB_TERM_COLOR_NORMAL);
|
||||
|
||||
grub_term_gotoxy (data->term, (struct grub_term_coordinate) {
|
||||
data->geo.first_entry_x, y });
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
if (unicode_title[i] == '\n' || unicode_title[i] == '\b'
|
||||
|| unicode_title[i] == '\r' || unicode_title[i] == '\e')
|
||||
unicode_title[i] = ' ';
|
||||
|
||||
if (data->geo.num_entries > 1)
|
||||
grub_putcode (highlight ? '*' : ' ', data->term);
|
||||
|
||||
grub_print_ucs4_menu (unicode_title,
|
||||
unicode_title + len,
|
||||
0,
|
||||
data->geo.right_margin,
|
||||
data->term, 0, 1,
|
||||
GRUB_UNICODE_RIGHTARROW, 0);
|
||||
|
||||
grub_term_setcolorstate (data->term, GRUB_TERM_COLOR_NORMAL);
|
||||
grub_term_gotoxy (data->term,
|
||||
(struct grub_term_coordinate) {
|
||||
grub_term_cursor_x (&data->geo), y });
|
||||
|
||||
grub_term_normal_color = old_color_normal;
|
||||
grub_term_highlight_color = old_color_highlight;
|
||||
|
||||
grub_term_setcolorstate (data->term, GRUB_TERM_COLOR_NORMAL);
|
||||
grub_free (unicode_title);
|
||||
}
|
||||
|
||||
static void
|
||||
print_entries (grub_menu_t menu, const struct menu_viewer_data *data)
|
||||
{
|
||||
grub_menu_entry_t e;
|
||||
int i;
|
||||
|
||||
grub_term_gotoxy (data->term,
|
||||
(struct grub_term_coordinate) {
|
||||
data->geo.first_entry_x + data->geo.entry_width
|
||||
+ data->geo.border + 1,
|
||||
data->geo.first_entry_y });
|
||||
|
||||
if (data->geo.num_entries != 1)
|
||||
{
|
||||
if (data->first)
|
||||
grub_putcode (GRUB_UNICODE_UPARROW, data->term);
|
||||
else
|
||||
grub_putcode (' ', data->term);
|
||||
}
|
||||
e = grub_menu_get_entry (menu, data->first);
|
||||
|
||||
for (i = 0; i < data->geo.num_entries; i++)
|
||||
{
|
||||
print_entry (data->geo.first_entry_y + i, data->offset == i,
|
||||
e, data);
|
||||
if (e)
|
||||
e = e->next;
|
||||
}
|
||||
|
||||
grub_term_gotoxy (data->term,
|
||||
(struct grub_term_coordinate) { data->geo.first_entry_x + data->geo.entry_width
|
||||
+ data->geo.border + 1,
|
||||
data->geo.first_entry_y + data->geo.num_entries - 1 });
|
||||
if (data->geo.num_entries == 1)
|
||||
{
|
||||
if (data->first && e)
|
||||
grub_putcode (GRUB_UNICODE_UPDOWNARROW, data->term);
|
||||
else if (data->first)
|
||||
grub_putcode (GRUB_UNICODE_UPARROW, data->term);
|
||||
else if (e)
|
||||
grub_putcode (GRUB_UNICODE_DOWNARROW, data->term);
|
||||
else
|
||||
grub_putcode (' ', data->term);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (e)
|
||||
grub_putcode (GRUB_UNICODE_DOWNARROW, data->term);
|
||||
else
|
||||
grub_putcode (' ', data->term);
|
||||
}
|
||||
|
||||
grub_term_gotoxy (data->term,
|
||||
(struct grub_term_coordinate) { grub_term_cursor_x (&data->geo),
|
||||
data->geo.first_entry_y + data->offset });
|
||||
}
|
||||
|
||||
/* Initialize the screen. If NESTED is non-zero, assume that this menu
|
||||
is run from another menu or a command-line. If EDIT is non-zero, show
|
||||
a message for the menu entry editor. */
|
||||
void
|
||||
grub_menu_init_page (int nested, int edit,
|
||||
struct grub_term_screen_geometry *geo,
|
||||
struct grub_term_output *term)
|
||||
{
|
||||
grub_uint8_t old_color_normal, old_color_highlight;
|
||||
int msg_num_lines;
|
||||
int bottom_message = 1;
|
||||
int empty_lines = 1;
|
||||
int version_msg = 1;
|
||||
|
||||
geo->border = 1;
|
||||
geo->first_entry_x = 1 /* margin */ + 1 /* border */;
|
||||
geo->entry_width = grub_term_width (term) - 5;
|
||||
|
||||
geo->first_entry_y = 2 /* two empty lines*/
|
||||
+ 1 /* GNU GRUB version text */ + 1 /* top border */;
|
||||
|
||||
geo->timeout_lines = 2;
|
||||
|
||||
/* 3 lines for timeout message and bottom margin. 2 lines for the border. */
|
||||
geo->num_entries = grub_term_height (term) - geo->first_entry_y
|
||||
- 1 /* bottom border */
|
||||
- 1 /* empty line before info message*/
|
||||
- geo->timeout_lines /* timeout */
|
||||
- 1 /* empty final line */;
|
||||
msg_num_lines = print_message (nested, edit, term, 1);
|
||||
if (geo->num_entries - msg_num_lines < 3
|
||||
|| geo->entry_width < 10)
|
||||
{
|
||||
geo->num_entries += 4;
|
||||
geo->first_entry_y -= 2;
|
||||
empty_lines = 0;
|
||||
geo->first_entry_x -= 1;
|
||||
geo->entry_width += 1;
|
||||
}
|
||||
if (geo->num_entries - msg_num_lines < 3
|
||||
|| geo->entry_width < 10)
|
||||
{
|
||||
geo->num_entries += 2;
|
||||
geo->first_entry_y -= 1;
|
||||
geo->first_entry_x -= 1;
|
||||
geo->entry_width += 2;
|
||||
geo->border = 0;
|
||||
}
|
||||
|
||||
if (geo->entry_width <= 0)
|
||||
geo->entry_width = 1;
|
||||
|
||||
if (geo->num_entries - msg_num_lines < 3
|
||||
&& geo->timeout_lines == 2)
|
||||
{
|
||||
geo->timeout_lines = 1;
|
||||
geo->num_entries++;
|
||||
}
|
||||
|
||||
if (geo->num_entries - msg_num_lines < 3)
|
||||
{
|
||||
geo->num_entries += 1;
|
||||
geo->first_entry_y -= 1;
|
||||
version_msg = 0;
|
||||
}
|
||||
|
||||
if (geo->num_entries - msg_num_lines >= 2)
|
||||
geo->num_entries -= msg_num_lines;
|
||||
else
|
||||
bottom_message = 0;
|
||||
|
||||
/* By default, use the same colors for the menu. */
|
||||
old_color_normal = grub_term_normal_color;
|
||||
old_color_highlight = grub_term_highlight_color;
|
||||
grub_color_menu_normal = grub_term_normal_color;
|
||||
grub_color_menu_highlight = grub_term_highlight_color;
|
||||
|
||||
/* Then give user a chance to replace them. */
|
||||
grub_parse_color_name_pair (&grub_color_menu_normal,
|
||||
grub_env_get ("menu_color_normal"));
|
||||
grub_parse_color_name_pair (&grub_color_menu_highlight,
|
||||
grub_env_get ("menu_color_highlight"));
|
||||
|
||||
if (version_msg)
|
||||
grub_normal_init_page (term, empty_lines);
|
||||
else
|
||||
grub_term_cls (term);
|
||||
|
||||
grub_term_normal_color = grub_color_menu_normal;
|
||||
grub_term_highlight_color = grub_color_menu_highlight;
|
||||
if (geo->border)
|
||||
draw_border (term, geo);
|
||||
grub_term_normal_color = old_color_normal;
|
||||
grub_term_highlight_color = old_color_highlight;
|
||||
geo->timeout_y = geo->first_entry_y + geo->num_entries
|
||||
+ geo->border + empty_lines;
|
||||
if (bottom_message)
|
||||
{
|
||||
grub_term_gotoxy (term,
|
||||
(struct grub_term_coordinate) { GRUB_TERM_MARGIN,
|
||||
geo->timeout_y });
|
||||
|
||||
print_message (nested, edit, term, 0);
|
||||
geo->timeout_y += msg_num_lines;
|
||||
}
|
||||
geo->right_margin = grub_term_width (term)
|
||||
- geo->first_entry_x
|
||||
- geo->entry_width - 1;
|
||||
}
|
||||
|
||||
static void
|
||||
menu_text_print_timeout (int timeout, void *dataptr)
|
||||
{
|
||||
struct menu_viewer_data *data = dataptr;
|
||||
char *msg_translated = 0;
|
||||
|
||||
grub_term_gotoxy (data->term,
|
||||
(struct grub_term_coordinate) { 0, data->geo.timeout_y });
|
||||
|
||||
if (data->timeout_msg == TIMEOUT_TERSE
|
||||
|| data->timeout_msg == TIMEOUT_TERSE_NO_MARGIN)
|
||||
msg_translated = grub_xasprintf (_("%ds"), timeout);
|
||||
else
|
||||
msg_translated = grub_xasprintf (_("The highlighted entry will be executed automatically in %ds."), timeout);
|
||||
if (!msg_translated)
|
||||
{
|
||||
grub_print_error ();
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (data->timeout_msg == TIMEOUT_UNKNOWN)
|
||||
{
|
||||
data->timeout_msg = grub_print_message_indented_real (msg_translated,
|
||||
3, 1, data->term, 1)
|
||||
<= data->geo.timeout_lines ? TIMEOUT_NORMAL : TIMEOUT_TERSE;
|
||||
if (data->timeout_msg == TIMEOUT_TERSE)
|
||||
{
|
||||
grub_free (msg_translated);
|
||||
msg_translated = grub_xasprintf (_("%ds"), timeout);
|
||||
if (grub_term_width (data->term) < 10)
|
||||
data->timeout_msg = TIMEOUT_TERSE_NO_MARGIN;
|
||||
}
|
||||
}
|
||||
|
||||
grub_print_message_indented (msg_translated,
|
||||
data->timeout_msg == TIMEOUT_TERSE_NO_MARGIN ? 0 : 3,
|
||||
data->timeout_msg == TIMEOUT_TERSE_NO_MARGIN ? 0 : 1,
|
||||
data->term);
|
||||
grub_free (msg_translated);
|
||||
|
||||
grub_term_gotoxy (data->term,
|
||||
(struct grub_term_coordinate) {
|
||||
grub_term_cursor_x (&data->geo),
|
||||
data->geo.first_entry_y + data->offset });
|
||||
grub_term_refresh (data->term);
|
||||
}
|
||||
|
||||
static void
|
||||
menu_text_set_chosen_entry (int entry, void *dataptr)
|
||||
{
|
||||
struct menu_viewer_data *data = dataptr;
|
||||
int oldoffset = data->offset;
|
||||
int complete_redraw = 0;
|
||||
|
||||
data->offset = entry - data->first;
|
||||
if (data->offset > data->geo.num_entries - 1)
|
||||
{
|
||||
data->first = entry - (data->geo.num_entries - 1);
|
||||
data->offset = data->geo.num_entries - 1;
|
||||
complete_redraw = 1;
|
||||
}
|
||||
if (data->offset < 0)
|
||||
{
|
||||
data->offset = 0;
|
||||
data->first = entry;
|
||||
complete_redraw = 1;
|
||||
}
|
||||
if (complete_redraw)
|
||||
print_entries (data->menu, data);
|
||||
else
|
||||
{
|
||||
print_entry (data->geo.first_entry_y + oldoffset, 0,
|
||||
grub_menu_get_entry (data->menu, data->first + oldoffset),
|
||||
data);
|
||||
print_entry (data->geo.first_entry_y + data->offset, 1,
|
||||
grub_menu_get_entry (data->menu, data->first + data->offset),
|
||||
data);
|
||||
}
|
||||
grub_term_refresh (data->term);
|
||||
}
|
||||
|
||||
static void
|
||||
menu_text_fini (void *dataptr)
|
||||
{
|
||||
struct menu_viewer_data *data = dataptr;
|
||||
|
||||
grub_term_setcursor (data->term, 1);
|
||||
grub_term_cls (data->term);
|
||||
grub_free (data);
|
||||
}
|
||||
|
||||
static void
|
||||
menu_text_clear_timeout (void *dataptr)
|
||||
{
|
||||
struct menu_viewer_data *data = dataptr;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < data->geo.timeout_lines;i++)
|
||||
{
|
||||
grub_term_gotoxy (data->term, (struct grub_term_coordinate) {
|
||||
0, data->geo.timeout_y + i });
|
||||
grub_print_spaces (data->term, grub_term_width (data->term) - 1);
|
||||
}
|
||||
if (data->geo.num_entries <= 5 && !data->geo.border)
|
||||
{
|
||||
grub_term_gotoxy (data->term,
|
||||
(struct grub_term_coordinate) {
|
||||
data->geo.first_entry_x + data->geo.entry_width
|
||||
+ data->geo.border + 1,
|
||||
data->geo.first_entry_y + data->geo.num_entries - 1
|
||||
});
|
||||
grub_putcode (' ', data->term);
|
||||
|
||||
data->geo.timeout_lines = 0;
|
||||
data->geo.num_entries++;
|
||||
print_entries (data->menu, data);
|
||||
}
|
||||
grub_term_gotoxy (data->term,
|
||||
(struct grub_term_coordinate) {
|
||||
grub_term_cursor_x (&data->geo),
|
||||
data->geo.first_entry_y + data->offset });
|
||||
grub_term_refresh (data->term);
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_menu_try_text (struct grub_term_output *term,
|
||||
int entry, grub_menu_t menu, int nested)
|
||||
{
|
||||
struct menu_viewer_data *data;
|
||||
struct grub_menu_viewer *instance;
|
||||
|
||||
instance = grub_zalloc (sizeof (*instance));
|
||||
if (!instance)
|
||||
return grub_errno;
|
||||
|
||||
data = grub_zalloc (sizeof (*data));
|
||||
if (!data)
|
||||
{
|
||||
grub_free (instance);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
data->term = term;
|
||||
instance->data = data;
|
||||
instance->set_chosen_entry = menu_text_set_chosen_entry;
|
||||
instance->print_timeout = menu_text_print_timeout;
|
||||
instance->clear_timeout = menu_text_clear_timeout;
|
||||
instance->fini = menu_text_fini;
|
||||
|
||||
data->menu = menu;
|
||||
|
||||
data->offset = entry;
|
||||
data->first = 0;
|
||||
|
||||
grub_term_setcursor (data->term, 0);
|
||||
grub_menu_init_page (nested, 0, &data->geo, data->term);
|
||||
|
||||
if (data->offset > data->geo.num_entries - 1)
|
||||
{
|
||||
data->first = data->offset - (data->geo.num_entries - 1);
|
||||
data->offset = data->geo.num_entries - 1;
|
||||
}
|
||||
|
||||
print_entries (menu, data);
|
||||
grub_term_refresh (data->term);
|
||||
grub_menu_register_viewer (instance);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
194
GRUB2/MOD_SRC/grub-2.04/grub-core/normal/misc.c
Normal file
@@ -0,0 +1,194 @@
|
||||
/* misc.c - miscellaneous functions */
|
||||
/*
|
||||
* 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/normal.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/fs.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/datetime.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/partition.h>
|
||||
|
||||
static const char *grub_human_sizes[3][6] =
|
||||
{
|
||||
/* This algorithm in reality would work only up to (2^64) / 100 B = 81 PiB.
|
||||
Put here all possible suffixes it can produce so no array bounds check
|
||||
is needed.
|
||||
*/
|
||||
/* TRANSLATORS: that's the list of binary unit prefixes. */
|
||||
{ N_("B"), N_("KiB"), N_("MiB"), N_("GiB"), N_("TiB"), N_("PiB")},
|
||||
/* TRANSLATORS: that's the list of binary unit prefixes. */
|
||||
{ "", N_("KB"), N_("MB"), N_("GB"), N_("TB"), N_("PB") },
|
||||
/* TRANSLATORS: that's the list of binary unit prefixes. */
|
||||
{ N_("B/s"), N_("KiB/s"), N_("MiB/s"), N_("GiB/s"), N_("TiB/s"), N_("PiB/s"), },
|
||||
};
|
||||
|
||||
const char *
|
||||
grub_get_human_size (grub_uint64_t size, enum grub_human_size_type type)
|
||||
{
|
||||
grub_uint64_t fsize;
|
||||
unsigned units = 0;
|
||||
static char buf[30];
|
||||
const char *umsg;
|
||||
|
||||
if (type != GRUB_HUMAN_SIZE_SPEED)
|
||||
fsize = size * 100ULL;
|
||||
else
|
||||
fsize = size;
|
||||
|
||||
/* Since 2^64 / 1024^5 < 102400, this can give at most 5 iterations.
|
||||
So units <=5, so impossible to go past the end of array.
|
||||
*/
|
||||
while (fsize >= 102400)
|
||||
{
|
||||
fsize = (fsize + 512) / 1024;
|
||||
units++;
|
||||
}
|
||||
|
||||
umsg = _(grub_human_sizes[type][units]);
|
||||
|
||||
if (units || type == GRUB_HUMAN_SIZE_SPEED)
|
||||
{
|
||||
grub_uint64_t whole, fraction;
|
||||
|
||||
whole = grub_divmod64 (fsize, 100, &fraction);
|
||||
grub_snprintf (buf, sizeof (buf),
|
||||
"%" PRIuGRUB_UINT64_T
|
||||
".%02" PRIuGRUB_UINT64_T "%s", whole, fraction,
|
||||
umsg);
|
||||
}
|
||||
else
|
||||
grub_snprintf (buf, sizeof (buf), "%llu%s", (unsigned long long) size,
|
||||
umsg);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* Print the information on the device NAME. */
|
||||
grub_err_t
|
||||
grub_normal_print_device_info (const char *name)
|
||||
{
|
||||
grub_device_t dev;
|
||||
char *p;
|
||||
|
||||
p = grub_strchr (name, ',');
|
||||
if (p)
|
||||
{
|
||||
grub_xputs ("\t");
|
||||
grub_printf_ (N_("Partition %s:"), name);
|
||||
grub_xputs (" ");
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_printf_ (N_("Device %s:"), name);
|
||||
grub_xputs (" ");
|
||||
}
|
||||
|
||||
dev = grub_device_open (name);
|
||||
if (! dev)
|
||||
grub_printf ("%s", _("Filesystem cannot be accessed"));
|
||||
else if (dev->disk)
|
||||
{
|
||||
grub_fs_t fs;
|
||||
|
||||
fs = grub_fs_probe (dev);
|
||||
/* Ignore all errors. */
|
||||
grub_errno = 0;
|
||||
|
||||
if (fs)
|
||||
{
|
||||
const char *fsname = fs->name;
|
||||
if (grub_strcmp (fsname, "ext2") == 0)
|
||||
fsname = "ext*";
|
||||
grub_printf_ (N_("Filesystem type %s"), fsname);
|
||||
if (fs->fs_label)
|
||||
{
|
||||
char *label;
|
||||
(fs->fs_label) (dev, &label);
|
||||
if (grub_errno == GRUB_ERR_NONE)
|
||||
{
|
||||
if (label && grub_strlen (label))
|
||||
{
|
||||
grub_xputs (" ");
|
||||
grub_printf_ (N_("- Label `%s'"), label);
|
||||
}
|
||||
grub_free (label);
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
if (fs->fs_mtime)
|
||||
{
|
||||
grub_int32_t tm;
|
||||
struct grub_datetime datetime;
|
||||
(fs->fs_mtime) (dev, &tm);
|
||||
if (grub_errno == GRUB_ERR_NONE)
|
||||
{
|
||||
grub_unixtime2datetime (tm, &datetime);
|
||||
grub_xputs (" ");
|
||||
/* TRANSLATORS: Arguments are year, month, day, hour, minute,
|
||||
second, day of the week (translated). */
|
||||
grub_printf_ (N_("- Last modification time %d-%02d-%02d "
|
||||
"%02d:%02d:%02d %s"),
|
||||
datetime.year, datetime.month, datetime.day,
|
||||
datetime.hour, datetime.minute, datetime.second,
|
||||
grub_get_weekday_name (&datetime));
|
||||
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
if (fs->fs_uuid)
|
||||
{
|
||||
char *uuid;
|
||||
(fs->fs_uuid) (dev, &uuid);
|
||||
if (grub_errno == GRUB_ERR_NONE)
|
||||
{
|
||||
if (uuid && grub_strlen (uuid))
|
||||
grub_printf (", UUID %s", uuid);
|
||||
grub_free (uuid);
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
}
|
||||
else
|
||||
grub_printf ("%s", _("No known filesystem detected"));
|
||||
|
||||
if (dev->disk->partition)
|
||||
grub_printf (_(" - Partition start at %llu%sKiB"),
|
||||
(unsigned long long) (grub_partition_get_start (dev->disk->partition) >> 1),
|
||||
(grub_partition_get_start (dev->disk->partition) & 1) ? ".5" : "" );
|
||||
else
|
||||
grub_printf_ (N_(" - Sector size %uB"), 1 << dev->disk->log_sector_size);
|
||||
if (grub_disk_get_size (dev->disk) == GRUB_DISK_SIZE_UNKNOWN)
|
||||
grub_puts_ (N_(" - Total size unknown"));
|
||||
else
|
||||
grub_printf (_(" - Total size %llu%sKiB"),
|
||||
(unsigned long long) (grub_disk_get_size (dev->disk) >> 1),
|
||||
/* TRANSLATORS: Replace dot with appropriate decimal separator for
|
||||
your language. */
|
||||
(grub_disk_get_size (dev->disk) & 1) ? _(".5") : "");
|
||||
}
|
||||
|
||||
if (dev)
|
||||
grub_device_close (dev);
|
||||
|
||||
grub_xputs ("\n");
|
||||
return grub_errno;
|
||||
}
|
@@ -23,7 +23,10 @@
|
||||
|
||||
#define VTOY_MAX_SCRIPT_BUF (4 * 1024 * 1024)
|
||||
|
||||
#define VTOY_SIZE_1GB 1073741824
|
||||
#define VTOY_FILT_MIN_FILE_SIZE 32768
|
||||
|
||||
#define VTOY_SIZE_1GB 1073741824
|
||||
#define VTOY_SIZE_512KB (512 * 1024)
|
||||
|
||||
#define JSON_SUCCESS 0
|
||||
#define JSON_FAILED 1
|
||||
@@ -62,6 +65,7 @@ typedef struct cmd_para
|
||||
grub_extcmd_t cmd;
|
||||
}cmd_para;
|
||||
|
||||
#define ventoy_align_2k(value) ((value + 2047) / 2048 * 2048)
|
||||
#define ventoy_align(value, align) (((value) + ((align) - 1)) & (~((align) - 1)))
|
||||
|
||||
#pragma pack(1)
|
||||
@@ -87,6 +91,7 @@ typedef struct cpio_newc_header
|
||||
|
||||
#define cmd_raw_name ctxt->extcmd->cmd->name
|
||||
#define check_free(p, func) if (p) { func(p); p = NULL; }
|
||||
#define grub_check_free(p) if (p) { grub_free(p); p = NULL; }
|
||||
|
||||
typedef int (*grub_char_check_func)(int c);
|
||||
#define ventoy_is_decimal(str) ventoy_string_check(str, grub_isdigit)
|
||||
@@ -118,15 +123,38 @@ typedef struct ventoy_udf_override
|
||||
grub_uint32_t position;
|
||||
}ventoy_udf_override;
|
||||
|
||||
typedef struct ventoy_iso9660_vd
|
||||
{
|
||||
grub_uint8_t type;
|
||||
grub_uint8_t id[5];
|
||||
grub_uint8_t ver;
|
||||
grub_uint8_t res;
|
||||
char sys[32];
|
||||
char vol[32];
|
||||
}ventoy_iso9660_vd;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
#define img_type_iso 0
|
||||
#define img_type_wim 1
|
||||
#define img_type_efi 2
|
||||
#define img_type_img 3
|
||||
|
||||
typedef struct img_info
|
||||
{
|
||||
int pathlen;
|
||||
char path[512];
|
||||
char name[256];
|
||||
|
||||
const char *alias;
|
||||
const char *class;
|
||||
const char *menu_prefix;
|
||||
|
||||
int id;
|
||||
int type;
|
||||
grub_uint64_t size;
|
||||
int select;
|
||||
int unsupport;
|
||||
|
||||
void *parent;
|
||||
|
||||
@@ -186,12 +214,15 @@ extern grub_uint8_t *g_ventoy_runtime_buf;
|
||||
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 int g_ventoy_debug;
|
||||
void ventoy_debug(const char *fmt, ...);
|
||||
#define debug(fmt, ...) if (g_ventoy_debug) ventoy_debug("[VTOY]: "fmt, __VA_ARGS__)
|
||||
|
||||
|
||||
#define vtoy_ssprintf(buf, pos, fmt, ...) \
|
||||
pos += grub_snprintf(buf + pos, VTOY_MAX_SCRIPT_BUF - pos, fmt, __VA_ARGS__)
|
||||
|
||||
#define FLAG_HEADER_RESERVED 0x00000001
|
||||
#define FLAG_HEADER_COMPRESSION 0x00000002
|
||||
@@ -204,6 +235,7 @@ void ventoy_debug(const char *fmt, ...);
|
||||
#define FLAG_HEADER_COMPRESS_RESERVED 0x00010000
|
||||
#define FLAG_HEADER_COMPRESS_XPRESS 0x00020000
|
||||
#define FLAG_HEADER_COMPRESS_LZX 0x00040000
|
||||
#define FLAG_HEADER_COMPRESS_LZMS 0x00080000
|
||||
|
||||
#define RESHDR_FLAG_FREE 0x01
|
||||
#define RESHDR_FLAG_METADATA 0x02
|
||||
@@ -350,6 +382,19 @@ typedef struct wim_tail
|
||||
grub_uint32_t new_lookup_align_len;
|
||||
}wim_tail;
|
||||
|
||||
typedef struct wim_patch
|
||||
{
|
||||
int pathlen;
|
||||
char path[256];
|
||||
|
||||
wim_hash old_hash;
|
||||
wim_tail wim_data;
|
||||
wim_lookup_entry *replace_look;
|
||||
|
||||
int valid;
|
||||
|
||||
struct wim_patch *next;
|
||||
}wim_patch;
|
||||
|
||||
|
||||
typedef enum _JSON_TYPE
|
||||
@@ -399,11 +444,13 @@ typedef struct _JSON_PARSE
|
||||
}
|
||||
|
||||
typedef int (*ventoy_plugin_entry_pf)(VTOY_JSON *json, const char *isodisk);
|
||||
typedef int (*ventoy_plugin_check_pf)(VTOY_JSON *json, const char *isodisk);
|
||||
|
||||
typedef struct plugin_entry
|
||||
{
|
||||
const char *key;
|
||||
ventoy_plugin_entry_pf entryfunc;
|
||||
ventoy_plugin_check_pf checkfunc;
|
||||
}plugin_entry;
|
||||
|
||||
|
||||
@@ -422,12 +469,15 @@ grub_err_t ventoy_cmd_valid_initrd_count(grub_extcmd_context_t ctxt, int argc, c
|
||||
grub_err_t ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
int ventoy_cpio_newc_fill_head(void *buf, int filesize, const void *filedata, const char *name);
|
||||
grub_file_t ventoy_grub_file_open(enum grub_file_type type, const char *fmt, ...);
|
||||
grub_uint64_t ventoy_grub_get_file_size(const char *fmt, ...);
|
||||
int ventoy_is_file_exist(const char *fmt, ...);
|
||||
int ventoy_is_dir_exist(const char *fmt, ...);
|
||||
int ventoy_fill_data(grub_uint32_t buflen, char *buffer);
|
||||
grub_err_t ventoy_cmd_load_plugin(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_wimdows_reset(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_wimdows_locate_wim(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_windows_chain_data(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_wim_chain_data(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_dump_wim_patch(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
|
||||
VTOY_JSON *vtoy_json_find_item
|
||||
(
|
||||
@@ -552,26 +602,126 @@ typedef struct ventoy_mbr_head
|
||||
}ventoy_mbr_head;
|
||||
#pragma pack()
|
||||
|
||||
typedef struct file_fullpath
|
||||
{
|
||||
char path[256];
|
||||
}file_fullpath;
|
||||
|
||||
typedef struct install_template
|
||||
{
|
||||
int pathlen;
|
||||
char isopath[256];
|
||||
char templatepath[256];
|
||||
|
||||
int autosel;
|
||||
int cursel;
|
||||
int templatenum;
|
||||
file_fullpath *templatepath;
|
||||
|
||||
struct install_template *next;
|
||||
}install_template;
|
||||
|
||||
typedef struct persistence_config
|
||||
{
|
||||
int pathlen;
|
||||
char isopath[256];
|
||||
|
||||
int autosel;
|
||||
int cursel;
|
||||
int backendnum;
|
||||
file_fullpath *backendpath;
|
||||
|
||||
struct persistence_config *next;
|
||||
}persistence_config;
|
||||
|
||||
#define vtoy_alias_image_file 0
|
||||
#define vtoy_alias_directory 1
|
||||
|
||||
typedef struct menu_alias
|
||||
{
|
||||
int type;
|
||||
int pathlen;
|
||||
char isopath[256];
|
||||
char alias[256];
|
||||
|
||||
struct menu_alias *next;
|
||||
}menu_alias;
|
||||
|
||||
#define vtoy_class_image_file 0
|
||||
#define vtoy_class_directory 1
|
||||
|
||||
typedef struct menu_class
|
||||
{
|
||||
int type;
|
||||
int patlen;
|
||||
char pattern[256];
|
||||
char class[64];
|
||||
|
||||
struct menu_class *next;
|
||||
}menu_class;
|
||||
|
||||
typedef struct injection_config
|
||||
{
|
||||
int pathlen;
|
||||
char isopath[256];
|
||||
char archive[256];
|
||||
|
||||
struct injection_config *next;
|
||||
}injection_config;
|
||||
|
||||
extern int g_ventoy_menu_esc;
|
||||
extern int g_ventoy_suppress_esc;
|
||||
extern int g_ventoy_last_entry;
|
||||
extern int g_ventoy_memdisk_mode;
|
||||
extern int g_ventoy_iso_raw;
|
||||
extern int g_ventoy_iso_uefi_drv;
|
||||
extern int g_ventoy_case_insensitive;
|
||||
extern grub_uint8_t g_ventoy_chain_type;
|
||||
|
||||
|
||||
#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_install_template(const char *isopath);
|
||||
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_get_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist, grub_disk_addr_t start);
|
||||
int ventoy_check_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist, grub_disk_addr_t start);
|
||||
void ventoy_plugin_dump_persistence(void);
|
||||
grub_err_t ventoy_cmd_plugin_check_json(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_linux_get_main_initrd_index(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_collect_wim_patch(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_wim_patch_count(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_locate_wim_patch(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_unix_chain_data(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
int ventoy_get_disk_guid(const char *filename, grub_uint8_t *guid);
|
||||
grub_err_t ventoy_cmd_unix_reset(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_unix_replace_conf(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_unix_replace_ko(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_unix_freebsd_ver(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_parse_freenas_ver(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
|
||||
#endif /* __VENTOY_DEF_H__ */
|
||||
|
@@ -42,6 +42,11 @@ static void json_debug(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
if (g_ventoy_debug == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
va_start (args, fmt);
|
||||
grub_vprintf (fmt, args);
|
||||
va_end (args);
|
@@ -38,8 +38,7 @@
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
|
||||
static char * ventoy_get_line(char *start)
|
||||
char * ventoy_get_line(char *start)
|
||||
{
|
||||
if (start == NULL)
|
||||
{
|
||||
@@ -686,6 +685,8 @@ static grub_uint32_t ventoy_linux_get_override_chunk_size(void)
|
||||
static void ventoy_linux_fill_override_data( grub_uint64_t isosize, void *override)
|
||||
{
|
||||
initrd_info *node;
|
||||
grub_uint32_t mod;
|
||||
grub_uint32_t newlen;
|
||||
grub_uint64_t sector;
|
||||
ventoy_override_chunk *cur;
|
||||
|
||||
@@ -699,13 +700,20 @@ static void ventoy_linux_fill_override_data( grub_uint64_t isosize, void *ove
|
||||
continue;
|
||||
}
|
||||
|
||||
newlen = (grub_uint32_t)(node->size + g_ventoy_cpio_size);
|
||||
mod = newlen % 4;
|
||||
if (mod > 0)
|
||||
{
|
||||
newlen += 4 - mod;
|
||||
}
|
||||
|
||||
if (node->iso_type == 0)
|
||||
{
|
||||
ventoy_iso9660_override *dirent = (ventoy_iso9660_override *)node->override_data;
|
||||
|
||||
node->override_length = sizeof(ventoy_iso9660_override);
|
||||
dirent->first_sector = (grub_uint32_t)sector;
|
||||
dirent->size = (grub_uint32_t)(node->size + g_ventoy_cpio_size);
|
||||
dirent->size = newlen;
|
||||
dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector);
|
||||
dirent->size_be = grub_swap_bytes32(dirent->size);
|
||||
|
||||
@@ -716,7 +724,7 @@ static void ventoy_linux_fill_override_data( grub_uint64_t isosize, void *ove
|
||||
ventoy_udf_override *udf = (ventoy_udf_override *)node->override_data;
|
||||
|
||||
node->override_length = sizeof(ventoy_udf_override);
|
||||
udf->length = (grub_uint32_t)(node->size + g_ventoy_cpio_size);
|
||||
udf->length = newlen;
|
||||
udf->position = (grub_uint32_t)sector - node->udf_start_block;
|
||||
|
||||
sector += (udf->length + 2047) / 2048;
|
||||
@@ -832,6 +840,50 @@ static grub_err_t ventoy_linux_locate_initrd(int filt, int *filtcnt)
|
||||
}
|
||||
|
||||
|
||||
grub_err_t ventoy_cmd_linux_get_main_initrd_index(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
int index = 0;
|
||||
char buf[32];
|
||||
initrd_info *node = NULL;
|
||||
|
||||
(void)ctxt;
|
||||
(void)argc;
|
||||
(void)args;
|
||||
|
||||
if (argc != 1)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (g_initrd_img_count == 1)
|
||||
{
|
||||
ventoy_set_env(args[0], "0");
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
||||
for (node = g_initrd_img_list; node; node = node->next)
|
||||
{
|
||||
if (node->size <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strstr(node->name, "ucode") || grub_strstr(node->name, "-firmware"))
|
||||
{
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
|
||||
grub_snprintf(buf, sizeof(buf), "%d", index);
|
||||
ventoy_set_env(args[0], buf);
|
||||
break;
|
||||
}
|
||||
|
||||
debug("main initrd index:%d\n", index);
|
||||
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_linux_locate_initrd(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
int sizefilt = 0;
|
||||
@@ -852,8 +904,12 @@ grub_err_t ventoy_cmd_linux_locate_initrd(grub_extcmd_context_t ctxt, int argc,
|
||||
|
||||
grub_err_t ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
int rc;
|
||||
char *template_file = NULL;
|
||||
char *template_buf = NULL;
|
||||
char *persistent_buf = NULL;
|
||||
char *injection_buf = NULL;
|
||||
const char *injection_file = NULL;
|
||||
grub_uint8_t *buf = NULL;
|
||||
grub_uint32_t mod;
|
||||
grub_uint32_t headlen;
|
||||
@@ -861,9 +917,12 @@ grub_err_t ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **arg
|
||||
grub_uint32_t padlen;
|
||||
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_file_t file;
|
||||
grub_file_t scriptfile;
|
||||
|
||||
grub_file_t tmpfile;
|
||||
ventoy_img_chunk_list chunk_list;
|
||||
|
||||
(void)ctxt;
|
||||
(void)argc;
|
||||
|
||||
@@ -892,30 +951,68 @@ grub_err_t ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **arg
|
||||
g_ventoy_cpio_size = 0;
|
||||
}
|
||||
|
||||
template_file = ventoy_plugin_get_install_template(args[1]);
|
||||
rc = ventoy_plugin_get_persistent_chunklist(args[1], -1, &chunk_list);
|
||||
if (rc == 0 && chunk_list.cur_chunk > 0 && chunk_list.chunk)
|
||||
{
|
||||
persistent_size = chunk_list.cur_chunk * sizeof(ventoy_img_chunk);
|
||||
persistent_buf = (char *)(chunk_list.chunk);
|
||||
}
|
||||
|
||||
template_file = ventoy_plugin_get_cur_install_template(args[1]);
|
||||
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
|
||||
{
|
||||
debug("Failed to open install script %s%s\n", args[2], template_file);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("auto install script skipped or not configed %s\n", args[1]);
|
||||
}
|
||||
|
||||
g_ventoy_cpio_buf = grub_malloc(file->size + 4096 + template_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]);
|
||||
}
|
||||
|
||||
g_ventoy_cpio_buf = grub_malloc(file->size + 4096 + template_size + persistent_size + injection_size + img_chunk_size);
|
||||
if (NULL == g_ventoy_cpio_buf)
|
||||
{
|
||||
grub_file_close(file);
|
||||
@@ -943,6 +1040,24 @@ grub_err_t ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **arg
|
||||
buf += headlen + ventoy_align(template_size, 4);
|
||||
}
|
||||
|
||||
if (persistent_size > 0 && persistent_buf)
|
||||
{
|
||||
headlen = ventoy_cpio_newc_fill_head(buf, persistent_size, persistent_buf, "ventoy/ventoy_persistent_map");
|
||||
buf += headlen + ventoy_align(persistent_size, 4);
|
||||
|
||||
grub_free(persistent_buf);
|
||||
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;
|
||||
}
|
||||
|
||||
/* step2: insert os param to cpio */
|
||||
headlen = ventoy_cpio_newc_fill_head(buf, 0, NULL, "ventoy/ventoy_os_param");
|
||||
padlen = sizeof(ventoy_os_param);
|
||||
@@ -1067,6 +1182,7 @@ grub_err_t ventoy_cmd_linux_chain_data(grub_extcmd_context_t ctxt, int argc, cha
|
||||
grub_memset(chain, 0, sizeof(ventoy_chain_head));
|
||||
|
||||
/* part 1: os parameter */
|
||||
g_ventoy_chain_type = ventoy_chain_linux;
|
||||
ventoy_fill_os_param(file, &(chain->os_param));
|
||||
|
||||
/* part 2: chain head */
|
1402
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_plugin.c
Normal file
1700
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_windows.c
Normal file
157
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/xpress.c
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Xpress Compression Algorithm (MS-XCA) decompression
|
||||
*
|
||||
*/
|
||||
|
||||
#include "wimboot.h"
|
||||
#include "huffman.h"
|
||||
#include "xpress.h"
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wcast-align"
|
||||
|
||||
/**
|
||||
* Decompress XCA-compressed data
|
||||
*
|
||||
* @v data Compressed data
|
||||
* @v len Length of compressed data
|
||||
* @v buf Decompression buffer, or NULL
|
||||
* @ret out_len Length of decompressed data, or negative error
|
||||
*/
|
||||
ssize_t xca_decompress ( const void *data, size_t len, void *buf ) {
|
||||
const void *src = data;
|
||||
const void *end = ( uint8_t * ) src + len;
|
||||
uint8_t *out = buf;
|
||||
size_t out_len = 0;
|
||||
size_t out_len_threshold = 0;
|
||||
const struct xca_huf_len *lengths;
|
||||
struct xca xca;
|
||||
uint32_t accum = 0;
|
||||
int extra_bits = 0;
|
||||
unsigned int huf;
|
||||
struct huffman_symbols *sym;
|
||||
unsigned int raw;
|
||||
unsigned int match_len;
|
||||
unsigned int match_offset_bits;
|
||||
unsigned int match_offset;
|
||||
const uint8_t *copy;
|
||||
int rc;
|
||||
|
||||
/* Process data stream */
|
||||
while ( src < end ) {
|
||||
|
||||
/* (Re)initialise decompressor if applicable */
|
||||
if ( out_len >= out_len_threshold ) {
|
||||
|
||||
/* Construct symbol lengths */
|
||||
lengths = src;
|
||||
src = ( uint8_t * ) src + sizeof ( *lengths );
|
||||
if ( src > end ) {
|
||||
DBG ( "XCA too short to hold Huffman lengths table.\n");
|
||||
return -1;
|
||||
}
|
||||
for ( raw = 0 ; raw < XCA_CODES ; raw++ )
|
||||
xca.lengths[raw] = xca_huf_len ( lengths, raw );
|
||||
|
||||
/* Construct Huffman alphabet */
|
||||
if ( ( rc = huffman_alphabet ( &xca.alphabet,
|
||||
xca.lengths,
|
||||
XCA_CODES ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Initialise state */
|
||||
accum = XCA_GET16 ( src );
|
||||
accum <<= 16;
|
||||
accum |= XCA_GET16 ( src );
|
||||
extra_bits = 16;
|
||||
|
||||
/* Determine next threshold */
|
||||
out_len_threshold = ( out_len + XCA_BLOCK_SIZE );
|
||||
}
|
||||
|
||||
/* Determine symbol */
|
||||
huf = ( accum >> ( 32 - HUFFMAN_BITS ) );
|
||||
sym = huffman_sym ( &xca.alphabet, huf );
|
||||
raw = huffman_raw ( sym, huf );
|
||||
accum <<= huffman_len ( sym );
|
||||
extra_bits -= huffman_len ( sym );
|
||||
if ( extra_bits < 0 ) {
|
||||
accum |= ( XCA_GET16 ( src ) << ( -extra_bits ) );
|
||||
extra_bits += 16;
|
||||
}
|
||||
|
||||
/* Process symbol */
|
||||
if ( raw < XCA_END_MARKER ) {
|
||||
|
||||
/* Literal symbol - add to output stream */
|
||||
if ( buf )
|
||||
*(out++) = raw;
|
||||
out_len++;
|
||||
|
||||
} else if ( ( raw == XCA_END_MARKER ) &&
|
||||
( (uint8_t *) src >= ( ( uint8_t * ) end - 1 ) ) ) {
|
||||
|
||||
/* End marker symbol */
|
||||
return out_len;
|
||||
|
||||
} else {
|
||||
|
||||
/* LZ77 match symbol */
|
||||
raw -= XCA_END_MARKER;
|
||||
match_offset_bits = ( raw >> 4 );
|
||||
match_len = ( raw & 0x0f );
|
||||
if ( match_len == 0x0f ) {
|
||||
match_len = XCA_GET8 ( src );
|
||||
if ( match_len == 0xff ) {
|
||||
match_len = XCA_GET16 ( src );
|
||||
} else {
|
||||
match_len += 0x0f;
|
||||
}
|
||||
}
|
||||
match_len += 3;
|
||||
if ( match_offset_bits ) {
|
||||
match_offset =
|
||||
( ( accum >> ( 32 - match_offset_bits ))
|
||||
+ ( 1 << match_offset_bits ) );
|
||||
} else {
|
||||
match_offset = 1;
|
||||
}
|
||||
accum <<= match_offset_bits;
|
||||
extra_bits -= match_offset_bits;
|
||||
if ( extra_bits < 0 ) {
|
||||
accum |= ( XCA_GET16 ( src ) << (-extra_bits) );
|
||||
extra_bits += 16;
|
||||
}
|
||||
|
||||
/* Copy data */
|
||||
out_len += match_len;
|
||||
if ( buf ) {
|
||||
copy = ( out - match_offset );
|
||||
while ( match_len-- )
|
||||
*(out++) = *(copy++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return out_len;
|
||||
}
|
87
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/xpress.h
Normal file
@@ -0,0 +1,87 @@
|
||||
#ifndef _XCA_H
|
||||
#define _XCA_H
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Xpress Compression Algorithm (MS-XCA) decompression
|
||||
*
|
||||
*/
|
||||
|
||||
#include "huffman.h"
|
||||
|
||||
/** Number of XCA codes */
|
||||
#define XCA_CODES 512
|
||||
|
||||
/** XCA decompressor */
|
||||
struct xca {
|
||||
/** Huffman alphabet */
|
||||
struct huffman_alphabet alphabet;
|
||||
/** Raw symbols
|
||||
*
|
||||
* Must immediately follow the Huffman alphabet.
|
||||
*/
|
||||
huffman_raw_symbol_t raw[XCA_CODES];
|
||||
/** Code lengths */
|
||||
uint8_t lengths[XCA_CODES];
|
||||
};
|
||||
|
||||
/** XCA symbol Huffman lengths table */
|
||||
struct xca_huf_len {
|
||||
/** Lengths of each symbol */
|
||||
uint8_t nibbles[ XCA_CODES / 2 ];
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/**
|
||||
* Extract Huffman-coded length of a raw symbol
|
||||
*
|
||||
* @v lengths Huffman lengths table
|
||||
* @v symbol Raw symbol
|
||||
* @ret len Huffman-coded length
|
||||
*/
|
||||
static inline unsigned int xca_huf_len ( const struct xca_huf_len *lengths,
|
||||
unsigned int symbol ) {
|
||||
return ( ( ( lengths->nibbles[ symbol / 2 ] ) >>
|
||||
( 4 * ( symbol % 2 ) ) ) & 0x0f );
|
||||
}
|
||||
|
||||
/** Get word from source data stream */
|
||||
#define XCA_GET16( src ) ( { \
|
||||
const uint16_t *src16 = src; \
|
||||
src = ( uint8_t * ) src + sizeof ( *src16 ); \
|
||||
*src16; } )
|
||||
|
||||
/** Get byte from source data stream */
|
||||
#define XCA_GET8( src ) ( { \
|
||||
const uint8_t *src8 = src; \
|
||||
src = ( uint8_t * ) src + sizeof ( *src8 ); \
|
||||
*src8; } )
|
||||
|
||||
/** XCA source data stream end marker */
|
||||
#define XCA_END_MARKER 256
|
||||
|
||||
/** XCA block size */
|
||||
#define XCA_BLOCK_SIZE ( 64 * 1024 )
|
||||
|
||||
extern ssize_t xca_decompress ( const void *data, size_t len, void *buf );
|
||||
|
||||
#endif /* _XCA_H */
|
243
GRUB2/MOD_SRC/grub-2.04/include/grub/file.h
Normal file
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2002,2007 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GRUB_FILE_HEADER
|
||||
#define GRUB_FILE_HEADER 1
|
||||
|
||||
#include <grub/types.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/device.h>
|
||||
#include <grub/fs.h>
|
||||
#include <grub/disk.h>
|
||||
|
||||
enum grub_file_type
|
||||
{
|
||||
GRUB_FILE_TYPE_NONE = 0,
|
||||
/* GRUB module to be loaded. */
|
||||
GRUB_FILE_TYPE_GRUB_MODULE,
|
||||
/* Loopback file to be represented as disk. */
|
||||
GRUB_FILE_TYPE_LOOPBACK,
|
||||
/* Linux kernel to be loaded. */
|
||||
GRUB_FILE_TYPE_LINUX_KERNEL,
|
||||
/* Linux initrd. */
|
||||
GRUB_FILE_TYPE_LINUX_INITRD,
|
||||
|
||||
/* Multiboot kernel. */
|
||||
GRUB_FILE_TYPE_MULTIBOOT_KERNEL,
|
||||
/* Multiboot module. */
|
||||
GRUB_FILE_TYPE_MULTIBOOT_MODULE,
|
||||
|
||||
/* Xen hypervisor - used on ARM only. */
|
||||
GRUB_FILE_TYPE_XEN_HYPERVISOR,
|
||||
/* Xen module - used on ARM only. */
|
||||
GRUB_FILE_TYPE_XEN_MODULE,
|
||||
|
||||
GRUB_FILE_TYPE_BSD_KERNEL,
|
||||
GRUB_FILE_TYPE_FREEBSD_ENV,
|
||||
GRUB_FILE_TYPE_FREEBSD_MODULE,
|
||||
GRUB_FILE_TYPE_FREEBSD_MODULE_ELF,
|
||||
GRUB_FILE_TYPE_NETBSD_MODULE,
|
||||
GRUB_FILE_TYPE_OPENBSD_RAMDISK,
|
||||
|
||||
GRUB_FILE_TYPE_XNU_INFO_PLIST,
|
||||
GRUB_FILE_TYPE_XNU_MKEXT,
|
||||
GRUB_FILE_TYPE_XNU_KEXT,
|
||||
GRUB_FILE_TYPE_XNU_KERNEL,
|
||||
GRUB_FILE_TYPE_XNU_RAMDISK,
|
||||
GRUB_FILE_TYPE_XNU_HIBERNATE_IMAGE,
|
||||
GRUB_FILE_XNU_DEVPROP,
|
||||
|
||||
GRUB_FILE_TYPE_PLAN9_KERNEL,
|
||||
|
||||
GRUB_FILE_TYPE_NTLDR,
|
||||
GRUB_FILE_TYPE_TRUECRYPT,
|
||||
GRUB_FILE_TYPE_FREEDOS,
|
||||
GRUB_FILE_TYPE_PXECHAINLOADER,
|
||||
GRUB_FILE_TYPE_PCCHAINLOADER,
|
||||
|
||||
GRUB_FILE_TYPE_COREBOOT_CHAINLOADER,
|
||||
|
||||
GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE,
|
||||
|
||||
/* File holding signature. */
|
||||
GRUB_FILE_TYPE_SIGNATURE,
|
||||
/* File holding public key to verify signature once. */
|
||||
GRUB_FILE_TYPE_PUBLIC_KEY,
|
||||
/* File holding public key to add to trused keys. */
|
||||
GRUB_FILE_TYPE_PUBLIC_KEY_TRUST,
|
||||
/* File of which we intend to print a blocklist to the user. */
|
||||
GRUB_FILE_TYPE_PRINT_BLOCKLIST,
|
||||
/* File we intend to use for test loading or testing speed. */
|
||||
GRUB_FILE_TYPE_TESTLOAD,
|
||||
/* File we open only to get its size. E.g. in ls output. */
|
||||
GRUB_FILE_TYPE_GET_SIZE,
|
||||
/* Font file. */
|
||||
GRUB_FILE_TYPE_FONT,
|
||||
/* File holding encryption key for encrypted ZFS. */
|
||||
GRUB_FILE_TYPE_ZFS_ENCRYPTION_KEY,
|
||||
/* File we open n grub-fstest. */
|
||||
GRUB_FILE_TYPE_FSTEST,
|
||||
/* File we open n grub-mount. */
|
||||
GRUB_FILE_TYPE_MOUNT,
|
||||
/* File which we attempt to identify the type of. */
|
||||
GRUB_FILE_TYPE_FILE_ID,
|
||||
/* File holding ACPI table. */
|
||||
GRUB_FILE_TYPE_ACPI_TABLE,
|
||||
/* File holding Device Tree. */
|
||||
GRUB_FILE_TYPE_DEVICE_TREE_IMAGE,
|
||||
/* File we intend show to user. */
|
||||
GRUB_FILE_TYPE_CAT,
|
||||
GRUB_FILE_TYPE_HEXCAT,
|
||||
/* One of pair of files we intend to compare. */
|
||||
GRUB_FILE_TYPE_CMP,
|
||||
/* List of hashes for hashsum. */
|
||||
GRUB_FILE_TYPE_HASHLIST,
|
||||
/* File hashed by hashsum. */
|
||||
GRUB_FILE_TYPE_TO_HASH,
|
||||
/* Keyboard layout. */
|
||||
GRUB_FILE_TYPE_KEYBOARD_LAYOUT,
|
||||
/* Picture file. */
|
||||
GRUB_FILE_TYPE_PIXMAP,
|
||||
/* *.lst shipped by GRUB. */
|
||||
GRUB_FILE_TYPE_GRUB_MODULE_LIST,
|
||||
/* config file. */
|
||||
GRUB_FILE_TYPE_CONFIG,
|
||||
GRUB_FILE_TYPE_THEME,
|
||||
GRUB_FILE_TYPE_GETTEXT_CATALOG,
|
||||
GRUB_FILE_TYPE_FS_SEARCH,
|
||||
GRUB_FILE_TYPE_AUDIO,
|
||||
GRUB_FILE_TYPE_VBE_DUMP,
|
||||
|
||||
GRUB_FILE_TYPE_LOADENV,
|
||||
GRUB_FILE_TYPE_SAVEENV,
|
||||
|
||||
GRUB_FILE_TYPE_VERIFY_SIGNATURE,
|
||||
|
||||
GRUB_FILE_TYPE_MASK = 0xffff,
|
||||
|
||||
/* --skip-sig is specified. */
|
||||
GRUB_FILE_TYPE_SKIP_SIGNATURE = 0x10000,
|
||||
GRUB_FILE_TYPE_NO_DECOMPRESS = 0x20000
|
||||
};
|
||||
|
||||
/* File description. */
|
||||
struct grub_file
|
||||
{
|
||||
/* File name. */
|
||||
char *name;
|
||||
|
||||
/* The underlying device. */
|
||||
grub_device_t device;
|
||||
|
||||
/* The underlying filesystem. */
|
||||
grub_fs_t fs;
|
||||
|
||||
/* The current offset. */
|
||||
grub_off_t offset;
|
||||
grub_off_t progress_offset;
|
||||
|
||||
/* Progress info. */
|
||||
grub_uint64_t last_progress_time;
|
||||
grub_off_t last_progress_offset;
|
||||
grub_uint64_t estimated_speed;
|
||||
|
||||
/* The file size. */
|
||||
grub_off_t size;
|
||||
|
||||
/* If file is not easily seekable. Should be set by underlying layer. */
|
||||
int not_easily_seekable;
|
||||
|
||||
/* Filesystem-specific data. */
|
||||
void *data;
|
||||
|
||||
/* This is called when a sector is read. Used only for a disk device. */
|
||||
grub_disk_read_hook_t read_hook;
|
||||
|
||||
/* Caller-specific data passed to the read hook. */
|
||||
void *read_hook_data;
|
||||
};
|
||||
typedef struct grub_file *grub_file_t;
|
||||
|
||||
extern grub_disk_read_hook_t EXPORT_VAR(grub_file_progress_hook);
|
||||
|
||||
/* Filters with lower ID are executed first. */
|
||||
typedef enum grub_file_filter_id
|
||||
{
|
||||
GRUB_FILE_FILTER_VERIFY,
|
||||
GRUB_FILE_FILTER_GZIO,
|
||||
GRUB_FILE_FILTER_XZIO,
|
||||
GRUB_FILE_FILTER_LZOPIO,
|
||||
GRUB_FILE_FILTER_MAX,
|
||||
GRUB_FILE_FILTER_COMPRESSION_FIRST = GRUB_FILE_FILTER_GZIO,
|
||||
GRUB_FILE_FILTER_COMPRESSION_LAST = GRUB_FILE_FILTER_LZOPIO,
|
||||
} grub_file_filter_id_t;
|
||||
|
||||
typedef grub_file_t (*grub_file_filter_t) (grub_file_t in, enum grub_file_type type);
|
||||
|
||||
extern grub_file_filter_t EXPORT_VAR(grub_file_filters)[GRUB_FILE_FILTER_MAX];
|
||||
|
||||
static inline void
|
||||
grub_file_filter_register (grub_file_filter_id_t id, grub_file_filter_t filter)
|
||||
{
|
||||
grub_file_filters[id] = filter;
|
||||
}
|
||||
|
||||
static inline void
|
||||
grub_file_filter_unregister (grub_file_filter_id_t id)
|
||||
{
|
||||
grub_file_filters[id] = 0;
|
||||
}
|
||||
|
||||
/* Get a device name from NAME. */
|
||||
char *EXPORT_FUNC(grub_file_get_device_name) (const char *name);
|
||||
|
||||
int EXPORT_FUNC(ventoy_check_file_exist) (const char * fmt, ...);
|
||||
grub_file_t EXPORT_FUNC(grub_file_open) (const char *name, enum grub_file_type type);
|
||||
grub_ssize_t EXPORT_FUNC(grub_file_read) (grub_file_t file, void *buf,
|
||||
grub_size_t len);
|
||||
grub_off_t EXPORT_FUNC(grub_file_seek) (grub_file_t file, grub_off_t offset);
|
||||
grub_err_t EXPORT_FUNC(grub_file_close) (grub_file_t file);
|
||||
|
||||
/* Return value of grub_file_size() in case file size is unknown. */
|
||||
#define GRUB_FILE_SIZE_UNKNOWN 0xffffffffffffffffULL
|
||||
|
||||
static inline grub_off_t
|
||||
grub_file_size (const grub_file_t file)
|
||||
{
|
||||
return file->size;
|
||||
}
|
||||
|
||||
static inline grub_off_t
|
||||
grub_file_tell (const grub_file_t file)
|
||||
{
|
||||
return file->offset;
|
||||
}
|
||||
|
||||
static inline int
|
||||
grub_file_seekable (const grub_file_t file)
|
||||
{
|
||||
return !file->not_easily_seekable;
|
||||
}
|
||||
|
||||
grub_file_t
|
||||
grub_file_offset_open (grub_file_t parent, enum grub_file_type type,
|
||||
grub_off_t start, grub_off_t size);
|
||||
void
|
||||
grub_file_offset_close (grub_file_t file);
|
||||
|
||||
#endif /* ! GRUB_FILE_HEADER */
|
@@ -35,10 +35,20 @@ typedef enum ventoy_fs_type
|
||||
ventoy_fs_ext, /* 2: ext2/ext3/ext4 */
|
||||
ventoy_fs_xfs, /* 3: XFS */
|
||||
ventoy_fs_udf, /* 4: UDF */
|
||||
ventoy_fs_fat, /* 5: FAT */
|
||||
|
||||
ventoy_fs_max
|
||||
}ventoy_fs_type;
|
||||
|
||||
typedef enum ventoy_chain_type
|
||||
{
|
||||
ventoy_chain_linux = 0, /* 0: linux */
|
||||
ventoy_chain_windows, /* 1: windows */
|
||||
ventoy_chain_wim, /* 2: wim */
|
||||
|
||||
ventoy_chain_max
|
||||
}ventoy_chain_type;
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
typedef struct ventoy_guid
|
||||
@@ -108,6 +118,9 @@ typedef struct ventoy_os_param
|
||||
*
|
||||
* vtoy_reserved[0]: vtoy_break_level
|
||||
* vtoy_reserved[1]: vtoy_debug_level
|
||||
* vtoy_reserved[2]: vtoy_chain_type 0:Linux 1:Windows 2:wimfile
|
||||
* vtoy_reserved[3]: vtoy_iso_format 0:iso9660 1:udf
|
||||
* vtoy_reserved[4]: vtoy_windows_cd_prompt
|
||||
*
|
||||
*/
|
||||
grub_uint8_t vtoy_reserved[32]; // Internal use by ventoy
|
||||
@@ -119,7 +132,8 @@ typedef struct 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;
|
||||
|
||||
|
||||
@@ -200,12 +214,13 @@ typedef struct ventoy_img_chunk_list
|
||||
|
||||
#define ventoy_filt_register grub_file_filter_register
|
||||
|
||||
typedef const char * (*grub_env_get_pf)(const char *name);
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
#define GRUB_FILE_REPLACE_MAGIC 0x1258BEEF
|
||||
|
||||
typedef const char * (*grub_env_get_pf)(const char *name);
|
||||
typedef int (*grub_env_printf_pf)(const char *fmt, ...);
|
||||
|
||||
typedef struct ventoy_grub_param_file_replace
|
||||
{
|
||||
grub_uint32_t magic;
|
||||
@@ -217,15 +232,16 @@ typedef struct ventoy_grub_param_file_replace
|
||||
typedef struct ventoy_grub_param
|
||||
{
|
||||
grub_env_get_pf grub_env_get;
|
||||
|
||||
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);
|
||||
grub_uint64_t grub_iso9660_get_last_read_pos(grub_file_t file);
|
||||
grub_uint64_t grub_iso9660_get_last_file_dirent_pos(grub_file_t file);
|
||||
grub_uint64_t grub_udf_get_file_offset(grub_file_t file);
|
60
GRUB2/MOD_SRC/grub-2.04/install.sh
Normal file
@@ -0,0 +1,60 @@
|
||||
#!/bin/bash
|
||||
|
||||
VT_DIR=$PWD/../../..
|
||||
|
||||
rm -rf $VT_DIR/GRUB2/INSTALL
|
||||
rm -rf $VT_DIR/GRUB2/PXE
|
||||
mkdir -p $VT_DIR/GRUB2/INSTALL
|
||||
mkdir -p $VT_DIR/GRUB2/PXE
|
||||
|
||||
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"
|
||||
|
||||
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"
|
||||
|
||||
if [ "$1" = "uefi" ]; then
|
||||
all_modules="$net_modules_uefi $all_modules_uefi "
|
||||
grub-mkimage -v --directory "$VT_DIR/GRUB2/INSTALL/lib/grub/x86_64-efi" --prefix '(,2)/grub' --output "$VT_DIR/INSTALL/EFI/BOOT/grubx64_real.efi" --format 'x86_64-efi' --compression 'auto' $all_modules_uefi 'fat' 'part_msdos'
|
||||
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'
|
||||
fi
|
||||
|
||||
grub-mknetdir --modules="$all_modules" --net-directory=$VT_DIR/GRUB2/PXE --subdir=grub2 --locales=en@quot || exit 1
|
||||
|
||||
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
|
||||
cp -a $VT_DIR/GRUB2/PXE/grub2/x86_64-efi/normal.mod $VT_DIR/INSTALL/grub/x86_64-efi/normal.mod || exit 1
|
||||
|
||||
#copy other modules
|
||||
ls -1 $VT_DIR/GRUB2/INSTALL/lib/grub/x86_64-efi/ | egrep '\.(lst|mod)$' | while read line; do
|
||||
if ! echo $all_modules | grep -q " ${line%.mod} "; then
|
||||
echo "Copy $line ..."
|
||||
rm -f $VT_DIR/INSTALL/grub/x86_64-efi/$line
|
||||
cp -a $VT_DIR/GRUB2/INSTALL/lib/grub/x86_64-efi/$line $VT_DIR/INSTALL/grub/x86_64-efi/
|
||||
fi
|
||||
done
|
||||
else
|
||||
rm -f $VT_DIR/GRUB2/NBP/core.0
|
||||
cp -a $VT_DIR/GRUB2/PXE/grub2/i386-pc/core.0 $VT_DIR/GRUB2/NBP/core.0 || exit 1
|
||||
|
||||
rm -f $VT_DIR/INSTALL/grub/i386-pc/boot.img
|
||||
cp -a $VT_DIR/GRUB2/INSTALL/lib/grub/i386-pc/boot.img $VT_DIR/INSTALL/grub/i386-pc/boot.img || exit 1
|
||||
|
||||
#copy other modules
|
||||
ls -1 $VT_DIR/GRUB2/INSTALL/lib/grub/i386-pc/ | egrep '\.(lst|mod)$' | while read line; do
|
||||
if ! echo $all_modules | grep -q " ${line%.mod} "; then
|
||||
echo "Copy $line ..."
|
||||
rm -f $VT_DIR/INSTALL/grub/i386-pc/$line
|
||||
cp -a $VT_DIR/GRUB2/INSTALL/lib/grub/i386-pc/$line $VT_DIR/INSTALL/grub/i386-pc/
|
||||
fi
|
||||
done
|
||||
fi
|
@@ -1,14 +0,0 @@
|
||||
|
||||
========== About Source Code =============
|
||||
Ventoy use grub-2.04, so I only put the added and modified source code here.
|
||||
|
||||
You can download grub-2.04 source code from this site:
|
||||
https://ftp.gnu.org/gnu/grub/
|
||||
|
||||
Just merge the code here with the original code of grub-2.04
|
||||
|
||||
|
||||
========== Build =============
|
||||
./autogen.sh
|
||||
./configure
|
||||
make
|
35
GRUB2/buildgrub.sh
Normal file
@@ -0,0 +1,35 @@
|
||||
#!/bin/bash
|
||||
|
||||
VT_GRUB_DIR=$PWD
|
||||
|
||||
rm -rf INSTALL
|
||||
rm -rf SRC
|
||||
rm -rf NBP
|
||||
rm -rf PXE
|
||||
|
||||
mkdir SRC
|
||||
mkdir NBP
|
||||
mkdir PXE
|
||||
|
||||
tar -xvf grub-2.04.tar.xz -C ./SRC/
|
||||
|
||||
/bin/cp -a ./MOD_SRC/grub-2.04 ./SRC/
|
||||
|
||||
cd ./SRC/grub-2.04
|
||||
|
||||
# build for Legacy BIOS
|
||||
./autogen.sh
|
||||
./configure --prefix=$VT_GRUB_DIR/INSTALL/
|
||||
make -j 16
|
||||
sh install.sh
|
||||
|
||||
# build for UEFI
|
||||
make distclean
|
||||
./autogen.sh
|
||||
./configure --with-platform=efi --prefix=$VT_GRUB_DIR/INSTALL/
|
||||
make -j 16
|
||||
sh install.sh uefi
|
||||
|
||||
|
||||
cd ../../
|
||||
|
@@ -1,249 +0,0 @@
|
||||
/******************************************************************************
|
||||
* ventoy_plugin.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+");
|
||||
|
||||
static install_template *g_install_template_head = NULL;
|
||||
|
||||
static int ventoy_plugin_theme_entry(VTOY_JSON *json, const char *isodisk)
|
||||
{
|
||||
const char *value;
|
||||
char filepath[256];
|
||||
|
||||
value = vtoy_json_get_string_ex(json->pstChild, "file");
|
||||
if (value)
|
||||
{
|
||||
if (value[0] == '/')
|
||||
{
|
||||
grub_snprintf(filepath, sizeof(filepath), "%s%s", isodisk, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_snprintf(filepath, sizeof(filepath), "%s/ventoy/%s", isodisk, value);
|
||||
}
|
||||
|
||||
if (ventoy_is_file_exist(filepath) == 0)
|
||||
{
|
||||
debug("Theme file %s does not exist\n", filepath);
|
||||
return 0;
|
||||
}
|
||||
|
||||
debug("vtoy_theme %s\n", filepath);
|
||||
grub_env_set("vtoy_theme", filepath);
|
||||
}
|
||||
|
||||
value = vtoy_json_get_string_ex(json->pstChild, "gfxmode");
|
||||
if (value)
|
||||
{
|
||||
debug("vtoy_gfxmode %s\n", value);
|
||||
grub_env_set("vtoy_gfxmode", value);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int ventoy_plugin_auto_install_entry(VTOY_JSON *json, const char *isodisk)
|
||||
{
|
||||
const char *iso = NULL;
|
||||
const char *script = NULL;
|
||||
VTOY_JSON *pNode = NULL;
|
||||
install_template *node = NULL;
|
||||
install_template *next = NULL;
|
||||
|
||||
(void)isodisk;
|
||||
|
||||
if (json->enDataType != JSON_TYPE_ARRAY)
|
||||
{
|
||||
debug("Not array %d\n", json->enDataType);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (g_install_template_head)
|
||||
{
|
||||
for (node = g_install_template_head; node; node = next)
|
||||
{
|
||||
next = node->next;
|
||||
grub_free(node);
|
||||
}
|
||||
|
||||
g_install_template_head = NULL;
|
||||
}
|
||||
|
||||
for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
|
||||
{
|
||||
iso = vtoy_json_get_string_ex(pNode->pstChild, "image");
|
||||
if (iso && iso[0] == '/')
|
||||
{
|
||||
script = vtoy_json_get_string_ex(pNode->pstChild, "template");
|
||||
if (script && script[0] == '/')
|
||||
{
|
||||
node = grub_zalloc(sizeof(install_template));
|
||||
if (node)
|
||||
{
|
||||
grub_snprintf(node->isopath, sizeof(node->isopath), "%s", iso);
|
||||
grub_snprintf(node->templatepath, sizeof(node->templatepath), "%s", script);
|
||||
|
||||
if (g_install_template_head)
|
||||
{
|
||||
node->next = g_install_template_head;
|
||||
}
|
||||
|
||||
g_install_template_head = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static plugin_entry g_plugin_entries[] =
|
||||
{
|
||||
{ "theme", ventoy_plugin_theme_entry },
|
||||
{ "auto_install", ventoy_plugin_auto_install_entry },
|
||||
};
|
||||
|
||||
static int ventoy_parse_plugin_config(VTOY_JSON *json, const char *isodisk)
|
||||
{
|
||||
int i;
|
||||
VTOY_JSON *cur = json;
|
||||
|
||||
while (cur)
|
||||
{
|
||||
for (i = 0; i < (int)ARRAY_SIZE(g_plugin_entries); i++)
|
||||
{
|
||||
if (grub_strcmp(g_plugin_entries[i].key, cur->pcName) == 0)
|
||||
{
|
||||
debug("Plugin entry for %s\n", g_plugin_entries[i].key);
|
||||
g_plugin_entries[i].entryfunc(cur, isodisk);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cur = cur->pstNext;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_load_plugin(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
int ret = 0;
|
||||
char *buf = NULL;
|
||||
grub_file_t file;
|
||||
VTOY_JSON *json = NULL;
|
||||
|
||||
(void)ctxt;
|
||||
(void)argc;
|
||||
|
||||
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s/ventoy/ventoy.json", args[0]);
|
||||
if (!file)
|
||||
{
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
debug("json configuration file size %d\n", (int)file->size);
|
||||
|
||||
buf = grub_malloc(file->size + 1);
|
||||
if (!buf)
|
||||
{
|
||||
grub_file_close(file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
buf[file->size] = 0;
|
||||
grub_file_read(file, buf, file->size);
|
||||
grub_file_close(file);
|
||||
|
||||
json = vtoy_json_create();
|
||||
if (!json)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ret = vtoy_json_parse(json, buf);
|
||||
if (ret)
|
||||
{
|
||||
debug("Failed to parse json string %d\n", ret);
|
||||
grub_free(buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ventoy_parse_plugin_config(json->pstChild, args[0]);
|
||||
|
||||
vtoy_json_destroy(json);
|
||||
|
||||
grub_free(buf);
|
||||
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
||||
|
||||
void ventoy_plugin_dump_auto_install(void)
|
||||
{
|
||||
install_template *node = NULL;
|
||||
|
||||
for (node = g_install_template_head; node; node = node->next)
|
||||
{
|
||||
grub_printf("IMAGE:<%s>\n", node->isopath);
|
||||
grub_printf("SCRIPT:<%s>\n\n", node->templatepath);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
char * ventoy_plugin_get_install_template(const char *isopath)
|
||||
{
|
||||
install_template *node = NULL;
|
||||
|
||||
for (node = g_install_template_head; node; node = node->next)
|
||||
{
|
||||
if (grub_strcmp(node->isopath, isopath) == 0)
|
||||
{
|
||||
return node->templatepath;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@@ -1,959 +0,0 @@
|
||||
/******************************************************************************
|
||||
* ventoy_windows.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/ventoy.h>
|
||||
#include "ventoy_def.h"
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
wim_hash g_old_hash;
|
||||
wim_tail g_wim_data;
|
||||
|
||||
static wim_lookup_entry *g_replace_look = NULL;
|
||||
|
||||
grub_ssize_t lzx_decompress ( const void *data, grub_size_t len, void *buf );
|
||||
|
||||
static int wim_name_cmp(const char *search, grub_uint16_t *name, grub_uint16_t namelen)
|
||||
{
|
||||
char c1 = vtoy_to_upper(*search);
|
||||
char c2 = vtoy_to_upper(*name);
|
||||
|
||||
while (namelen > 0 && (c1 == c2))
|
||||
{
|
||||
search++;
|
||||
name++;
|
||||
namelen--;
|
||||
|
||||
c1 = vtoy_to_upper(*search);
|
||||
c2 = vtoy_to_upper(*name);
|
||||
}
|
||||
|
||||
if (namelen == 0 && *search == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ventoy_is_pe64(grub_uint8_t *buffer)
|
||||
{
|
||||
grub_uint32_t pe_off;
|
||||
|
||||
if (buffer[0] != 'M' || buffer[1] != 'Z')
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
pe_off = *(grub_uint32_t *)(buffer + 60);
|
||||
|
||||
if (buffer[pe_off] != 'P' || buffer[pe_off + 1] != 'E')
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*(grub_uint16_t *)(buffer + pe_off + 24) == 0x020b)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_wimdows_reset(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
(void)ctxt;
|
||||
(void)argc;
|
||||
(void)args;
|
||||
|
||||
check_free(g_wim_data.jump_bin_data, grub_free);
|
||||
check_free(g_wim_data.new_meta_data, grub_free);
|
||||
check_free(g_wim_data.new_lookup_data, grub_free);
|
||||
|
||||
grub_memset(&g_wim_data, 0, sizeof(g_wim_data));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ventoy_load_jump_exe(const char *path, grub_uint8_t **data, grub_uint32_t *size, wim_hash *hash)
|
||||
{
|
||||
grub_uint32_t i;
|
||||
grub_uint32_t align;
|
||||
grub_file_t file;
|
||||
|
||||
debug("windows load jump %s\n", path);
|
||||
|
||||
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", path);
|
||||
if (!file)
|
||||
{
|
||||
debug("Can't open file %s\n", path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
align = ventoy_align((int)file->size, 2048);
|
||||
|
||||
debug("file %s size:%d align:%u\n", path, (int)file->size, align);
|
||||
|
||||
*size = (grub_uint32_t)file->size;
|
||||
*data = (grub_uint8_t *)grub_malloc(align);
|
||||
if ((*data) == NULL)
|
||||
{
|
||||
debug("Failed to alloc memory size %u\n", align);
|
||||
goto end;
|
||||
}
|
||||
|
||||
grub_file_read(file, (*data), file->size);
|
||||
|
||||
if (hash)
|
||||
{
|
||||
grub_crypto_hash(GRUB_MD_SHA1, hash->sha1, (*data), file->size);
|
||||
|
||||
if (g_ventoy_debug)
|
||||
{
|
||||
debug("%s", "jump bin 64 hash: ");
|
||||
for (i = 0; i < sizeof(hash->sha1); i++)
|
||||
{
|
||||
ventoy_debug("%02x ", hash->sha1[i]);
|
||||
}
|
||||
ventoy_debug("\n");
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
|
||||
grub_file_close(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ventoy_get_override_info(grub_file_t file)
|
||||
{
|
||||
grub_uint32_t start_block;
|
||||
grub_uint64_t file_offset;
|
||||
grub_uint64_t override_offset;
|
||||
grub_uint32_t override_len;
|
||||
grub_uint64_t fe_entry_size_offset;
|
||||
|
||||
if (grub_strcmp(file->fs->name, "iso9660") == 0)
|
||||
{
|
||||
g_wim_data.iso_type = 0;
|
||||
override_len = sizeof(ventoy_iso9660_override);
|
||||
override_offset = grub_iso9660_get_last_file_dirent_pos(file) + 2;
|
||||
|
||||
grub_file_read(file, &start_block, 1); // just read for hook trigger
|
||||
file_offset = grub_iso9660_get_last_read_pos(file);
|
||||
|
||||
debug("iso9660 wim size:%llu override_offset:%llu file_offset:%llu\n",
|
||||
(ulonglong)file->size, (ulonglong)override_offset, (ulonglong)file_offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_wim_data.iso_type = 1;
|
||||
override_len = sizeof(ventoy_udf_override);
|
||||
override_offset = grub_udf_get_last_file_attr_offset(file, &start_block, &fe_entry_size_offset);
|
||||
|
||||
file_offset = grub_udf_get_file_offset(file);
|
||||
|
||||
debug("UDF wim size:%llu override_offset:%llu file_offset:%llu start_block=%u\n",
|
||||
(ulonglong)file->size, (ulonglong)override_offset, (ulonglong)file_offset, start_block);
|
||||
}
|
||||
|
||||
g_wim_data.file_offset = file_offset;
|
||||
g_wim_data.udf_start_block = start_block;
|
||||
g_wim_data.fe_entry_size_offset = fe_entry_size_offset;
|
||||
g_wim_data.override_offset = override_offset;
|
||||
g_wim_data.override_len = override_len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ventoy_read_resource(grub_file_t fp, wim_resource_header *head, void **buffer)
|
||||
{
|
||||
int decompress_len = 0;
|
||||
int total_decompress = 0;
|
||||
grub_uint32_t i = 0;
|
||||
grub_uint32_t chunk_num = 0;
|
||||
grub_uint32_t chunk_size = 0;
|
||||
grub_uint32_t last_chunk_size = 0;
|
||||
grub_uint32_t last_decompress_size = 0;
|
||||
grub_uint32_t cur_offset = 0;
|
||||
grub_uint8_t *cur_dst = NULL;
|
||||
grub_uint8_t *buffer_compress = NULL;
|
||||
grub_uint8_t *buffer_decompress = NULL;
|
||||
grub_uint32_t *chunk_offset = NULL;
|
||||
|
||||
buffer_decompress = (grub_uint8_t *)grub_malloc(head->raw_size + head->size_in_wim);
|
||||
if (NULL == buffer_decompress)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_file_seek(fp, head->offset);
|
||||
|
||||
if (head->size_in_wim == head->raw_size)
|
||||
{
|
||||
grub_file_read(fp, buffer_decompress, head->size_in_wim);
|
||||
*buffer = buffer_decompress;
|
||||
return 0;
|
||||
}
|
||||
|
||||
buffer_compress = buffer_decompress + head->raw_size;
|
||||
grub_file_read(fp, buffer_compress, head->size_in_wim);
|
||||
|
||||
chunk_num = (head->raw_size + WIM_CHUNK_LEN - 1) / WIM_CHUNK_LEN;
|
||||
cur_offset = (chunk_num - 1) * 4;
|
||||
chunk_offset = (grub_uint32_t *)buffer_compress;
|
||||
|
||||
cur_dst = buffer_decompress;
|
||||
|
||||
for (i = 0; i < chunk_num - 1; i++)
|
||||
{
|
||||
chunk_size = (i == 0) ? chunk_offset[i] : chunk_offset[i] - chunk_offset[i - 1];
|
||||
|
||||
if (WIM_CHUNK_LEN == chunk_size)
|
||||
{
|
||||
grub_memcpy(cur_dst, buffer_compress + cur_offset, chunk_size);
|
||||
decompress_len = (int)chunk_size;
|
||||
}
|
||||
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);
|
||||
|
||||
total_decompress += decompress_len;
|
||||
cur_dst += decompress_len;
|
||||
cur_offset += chunk_size;
|
||||
}
|
||||
|
||||
/* last chunk */
|
||||
last_chunk_size = (grub_uint32_t)(head->size_in_wim - cur_offset);
|
||||
last_decompress_size = head->raw_size - total_decompress;
|
||||
|
||||
if (last_chunk_size < WIM_CHUNK_LEN && last_chunk_size == last_decompress_size)
|
||||
{
|
||||
debug("Last chunk %u uncompressed\n", last_chunk_size);
|
||||
grub_memcpy(cur_dst, buffer_compress + cur_offset, last_chunk_size);
|
||||
decompress_len = (int)last_chunk_size;
|
||||
}
|
||||
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;
|
||||
|
||||
if (cur_dst != buffer_decompress + head->raw_size)
|
||||
{
|
||||
debug("head->size_in_wim:%llu head->raw_size:%llu cur_dst:%p buffer_decompress:%p total_decompress:%d\n",
|
||||
(ulonglong)head->size_in_wim, (ulonglong)head->raw_size, cur_dst, buffer_decompress, total_decompress);
|
||||
grub_free(buffer_decompress);
|
||||
return 1;
|
||||
}
|
||||
|
||||
*buffer = buffer_decompress;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static wim_directory_entry * search_wim_dirent(wim_directory_entry *dir, const char *search_name)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (dir->len && dir->name_len)
|
||||
{
|
||||
if (wim_name_cmp(search_name, (grub_uint16_t *)(dir + 1), dir->name_len / 2) == 0)
|
||||
{
|
||||
return dir;
|
||||
}
|
||||
}
|
||||
dir = (wim_directory_entry *)((grub_uint8_t *)dir + dir->len);
|
||||
} while(dir->len);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static wim_directory_entry * search_full_wim_dirent
|
||||
(
|
||||
void *meta_data,
|
||||
wim_directory_entry *dir,
|
||||
const char **path
|
||||
)
|
||||
{
|
||||
wim_directory_entry *subdir = NULL;
|
||||
wim_directory_entry *search = dir;
|
||||
|
||||
while (*path)
|
||||
{
|
||||
subdir = (wim_directory_entry *)((char *)meta_data + search->subdir);
|
||||
search = search_wim_dirent(subdir, *path);
|
||||
if (!search)
|
||||
{
|
||||
debug("%s search failed\n", *path);
|
||||
}
|
||||
|
||||
path++;
|
||||
}
|
||||
return search;
|
||||
}
|
||||
|
||||
static wim_directory_entry * search_replace_wim_dirent(void *meta_data, wim_directory_entry *dir)
|
||||
{
|
||||
wim_directory_entry *wim_dirent = NULL;
|
||||
const char *winpeshl_path[] = { "Windows", "System32", "winpeshl.exe", NULL };
|
||||
const char *pecmd_path[] = { "Windows", "System32", "PECMD.exe", NULL };
|
||||
|
||||
wim_dirent = search_full_wim_dirent(meta_data, dir, winpeshl_path);
|
||||
if (wim_dirent)
|
||||
{
|
||||
return wim_dirent;
|
||||
}
|
||||
|
||||
wim_dirent = search_full_wim_dirent(meta_data, dir, pecmd_path);
|
||||
if (wim_dirent)
|
||||
{
|
||||
return wim_dirent;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static wim_lookup_entry * ventoy_find_look_entry(wim_header *header, wim_lookup_entry *lookup, wim_hash *hash)
|
||||
{
|
||||
grub_uint32_t i = 0;
|
||||
|
||||
for (i = 0; i < (grub_uint32_t)header->lookup.raw_size / sizeof(wim_lookup_entry); i++)
|
||||
{
|
||||
if (grub_memcmp(&lookup[i].hash, hash, sizeof(wim_hash)) == 0)
|
||||
{
|
||||
return lookup + i;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static wim_lookup_entry * ventoy_find_meta_entry(wim_header *header, wim_lookup_entry *lookup)
|
||||
{
|
||||
grub_uint32_t i = 0;
|
||||
grub_uint32_t index = 0;;
|
||||
|
||||
if ((header == NULL) || (lookup == NULL))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < (grub_uint32_t)header->lookup.raw_size / sizeof(wim_lookup_entry); i++)
|
||||
{
|
||||
if (lookup[i].resource.flags & RESHDR_FLAG_METADATA)
|
||||
{
|
||||
index++;
|
||||
if (index == header->boot_index)
|
||||
{
|
||||
return lookup + i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int ventoy_update_all_hash(void *meta_data, wim_directory_entry *dir)
|
||||
{
|
||||
if ((meta_data == NULL) || (dir == NULL))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dir->len < sizeof(wim_directory_entry))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if (dir->subdir == 0 && grub_memcmp(dir->hash.sha1, g_old_hash.sha1, sizeof(wim_hash)) == 0)
|
||||
{
|
||||
debug("find target file, name_len:%u upadte hash\n", dir->name_len);
|
||||
grub_memcpy(dir->hash.sha1, &(g_wim_data.bin_hash), sizeof(wim_hash));
|
||||
}
|
||||
|
||||
if (dir->subdir)
|
||||
{
|
||||
ventoy_update_all_hash(meta_data, (wim_directory_entry *)((char *)meta_data + dir->subdir));
|
||||
}
|
||||
|
||||
dir = (wim_directory_entry *)((char *)dir + dir->len);
|
||||
} while (dir->len >= sizeof(wim_directory_entry));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ventoy_cat_exe_file_data(grub_uint32_t exe_len, grub_uint8_t *exe_data)
|
||||
{
|
||||
int pe64 = 0;
|
||||
char file[256];
|
||||
grub_uint32_t jump_len = 0;
|
||||
grub_uint32_t jump_align = 0;
|
||||
grub_uint8_t *jump_data = NULL;
|
||||
|
||||
pe64 = ventoy_is_pe64(exe_data);
|
||||
|
||||
grub_snprintf(file, sizeof(file), "%s/vtoyjump%d.exe", grub_env_get("vtoy_path"), pe64 ? 64 : 32);
|
||||
ventoy_load_jump_exe(file, &jump_data, &jump_len, NULL);
|
||||
jump_align = ventoy_align(jump_len, 16);
|
||||
|
||||
g_wim_data.jump_exe_len = jump_len;
|
||||
g_wim_data.bin_raw_len = jump_align + sizeof(ventoy_os_param) + sizeof(ventoy_windows_data) + exe_len;
|
||||
g_wim_data.bin_align_len = ventoy_align(g_wim_data.bin_raw_len, 2048);
|
||||
|
||||
g_wim_data.jump_bin_data = grub_malloc(g_wim_data.bin_align_len);
|
||||
if (g_wim_data.jump_bin_data)
|
||||
{
|
||||
grub_memcpy(g_wim_data.jump_bin_data, jump_data, jump_len);
|
||||
grub_memcpy(g_wim_data.jump_bin_data + jump_align + sizeof(ventoy_os_param) + sizeof(ventoy_windows_data), exe_data, exe_len);
|
||||
}
|
||||
|
||||
debug("jump_exe_len:%u bin_raw_len:%u bin_align_len:%u\n",
|
||||
g_wim_data.jump_exe_len, g_wim_data.bin_raw_len, g_wim_data.bin_align_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ventoy_fill_windows_rtdata(void *buf, char *isopath)
|
||||
{
|
||||
char *pos = NULL;
|
||||
char *script = NULL;
|
||||
ventoy_windows_data *data = (ventoy_windows_data *)buf;
|
||||
|
||||
grub_memset(data, 0, sizeof(ventoy_windows_data));
|
||||
|
||||
pos = grub_strstr(isopath, "/");
|
||||
if (!pos)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
script = ventoy_plugin_get_install_template(pos);
|
||||
if (script)
|
||||
{
|
||||
debug("auto install script <%s>\n", script);
|
||||
grub_snprintf(data->auto_install_script, sizeof(data->auto_install_script) - 1, "%s", script);
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("auto install script not found %p\n", pos);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ventoy_update_before_chain(ventoy_os_param *param, char *isopath)
|
||||
{
|
||||
grub_uint32_t jump_align = 0;
|
||||
wim_lookup_entry *meta_look = NULL;
|
||||
wim_security_header *security = NULL;
|
||||
wim_directory_entry *rootdir = NULL;
|
||||
wim_header *head = &(g_wim_data.wim_header);
|
||||
wim_lookup_entry *lookup = (wim_lookup_entry *)g_wim_data.new_lookup_data;
|
||||
|
||||
jump_align = ventoy_align(g_wim_data.jump_exe_len, 16);
|
||||
if (g_wim_data.jump_bin_data)
|
||||
{
|
||||
grub_memcpy(g_wim_data.jump_bin_data + jump_align, param, sizeof(ventoy_os_param));
|
||||
ventoy_fill_windows_rtdata(g_wim_data.jump_bin_data + jump_align + sizeof(ventoy_os_param), isopath);
|
||||
}
|
||||
|
||||
grub_crypto_hash(GRUB_MD_SHA1, g_wim_data.bin_hash.sha1, g_wim_data.jump_bin_data, g_wim_data.bin_raw_len);
|
||||
|
||||
security = (wim_security_header *)g_wim_data.new_meta_data;
|
||||
rootdir = (wim_directory_entry *)(g_wim_data.new_meta_data + ((security->len + 7) & 0xFFFFFFF8U));
|
||||
|
||||
/* update all winpeshl.exe dirent entry's hash */
|
||||
ventoy_update_all_hash(g_wim_data.new_meta_data, rootdir);
|
||||
|
||||
/* update winpeshl.exe lookup entry data (hash/offset/length) */
|
||||
if (g_replace_look)
|
||||
{
|
||||
debug("update replace lookup entry_id:%ld\n", ((long)g_replace_look - (long)lookup) / sizeof(wim_lookup_entry));
|
||||
g_replace_look->resource.raw_size = g_wim_data.bin_raw_len;
|
||||
g_replace_look->resource.size_in_wim = g_wim_data.bin_raw_len;
|
||||
g_replace_look->resource.flags = 0;
|
||||
g_replace_look->resource.offset = g_wim_data.wim_align_size;
|
||||
|
||||
grub_memcpy(g_replace_look->hash.sha1, g_wim_data.bin_hash.sha1, sizeof(wim_hash));
|
||||
}
|
||||
|
||||
/* update metadata's hash */
|
||||
meta_look = ventoy_find_meta_entry(head, lookup);
|
||||
if (meta_look)
|
||||
{
|
||||
debug("find meta lookup entry_id:%ld\n", ((long)meta_look - (long)lookup) / sizeof(wim_lookup_entry));
|
||||
grub_memcpy(&meta_look->resource, &head->metadata, sizeof(wim_resource_header));
|
||||
grub_crypto_hash(GRUB_MD_SHA1, meta_look->hash.sha1, g_wim_data.new_meta_data, g_wim_data.new_meta_len);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_wimdows_locate_wim(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
int rc;
|
||||
grub_file_t file;
|
||||
grub_uint32_t exe_len;
|
||||
grub_uint8_t *exe_data = NULL;
|
||||
grub_uint8_t *decompress_data = NULL;
|
||||
wim_lookup_entry *lookup = NULL;
|
||||
wim_security_header *security = NULL;
|
||||
wim_directory_entry *rootdir = NULL;
|
||||
wim_directory_entry *search = NULL;
|
||||
wim_header *head = &(g_wim_data.wim_header);
|
||||
|
||||
(void)ctxt;
|
||||
(void)argc;
|
||||
|
||||
debug("windows locate wim start %s\n", args[0]);
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
ventoy_get_override_info(file);
|
||||
|
||||
grub_file_seek(file, 0);
|
||||
grub_file_read(file, head, sizeof(wim_header));
|
||||
|
||||
if (grub_memcmp(head->signature, WIM_HEAD_SIGNATURE, sizeof(head->signature)))
|
||||
{
|
||||
debug("Not a valid wim file %s\n", (char *)head->signature);
|
||||
grub_file_close(file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (head->flags & FLAG_HEADER_COMPRESS_XPRESS)
|
||||
{
|
||||
debug("Xpress 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);
|
||||
if (rc)
|
||||
{
|
||||
grub_printf("failed to read meta data %d\n", rc);
|
||||
grub_file_close(file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
security = (wim_security_header *)decompress_data;
|
||||
rootdir = (wim_directory_entry *)(decompress_data + ((security->len + 7) & 0xFFFFFFF8U));
|
||||
|
||||
/* search winpeshl.exe dirent entry */
|
||||
search = search_replace_wim_dirent(decompress_data, rootdir);
|
||||
if (!search)
|
||||
{
|
||||
debug("Failed to find replace file %p\n", search);
|
||||
grub_file_close(file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
debug("find replace file at %p\n", search);
|
||||
|
||||
grub_memcpy(&g_old_hash, search->hash.sha1, sizeof(wim_hash));
|
||||
|
||||
debug("read lookup offset:%llu size:%llu\n", (ulonglong)head->lookup.offset, (ulonglong)head->lookup.raw_size);
|
||||
lookup = grub_malloc(head->lookup.raw_size);
|
||||
grub_file_seek(file, head->lookup.offset);
|
||||
grub_file_read(file, lookup, head->lookup.raw_size);
|
||||
|
||||
/* find and extact winpeshl.exe */
|
||||
g_replace_look = ventoy_find_look_entry(head, lookup, &g_old_hash);
|
||||
if (g_replace_look)
|
||||
{
|
||||
exe_len = (grub_uint32_t)g_replace_look->resource.raw_size;
|
||||
debug("find replace lookup entry_id:%ld raw_size:%u\n",
|
||||
((long)g_replace_look - (long)lookup) / sizeof(wim_lookup_entry), exe_len);
|
||||
|
||||
if (0 == ventoy_read_resource(file, &(g_replace_look->resource), (void **)&(exe_data)))
|
||||
{
|
||||
ventoy_cat_exe_file_data(exe_len, exe_data);
|
||||
grub_free(exe_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("failed to read replace file meta data %u\n", exe_len);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("failed to find lookup entry for replace file 0x%02x 0x%02x\n", g_old_hash.sha1[0], g_old_hash.sha1[1]);
|
||||
}
|
||||
|
||||
g_wim_data.wim_raw_size = (grub_uint32_t)file->size;
|
||||
g_wim_data.wim_align_size = ventoy_align(g_wim_data.wim_raw_size, 2048);
|
||||
|
||||
check_free(g_wim_data.new_meta_data, grub_free);
|
||||
g_wim_data.new_meta_data = decompress_data;
|
||||
g_wim_data.new_meta_len = head->metadata.raw_size;
|
||||
g_wim_data.new_meta_align_len = ventoy_align(g_wim_data.new_meta_len, 2048);
|
||||
|
||||
check_free(g_wim_data.new_lookup_data, grub_free);
|
||||
g_wim_data.new_lookup_data = (grub_uint8_t *)lookup;
|
||||
g_wim_data.new_lookup_len = (grub_uint32_t)head->lookup.raw_size;
|
||||
g_wim_data.new_lookup_align_len = ventoy_align(g_wim_data.new_lookup_len, 2048);
|
||||
|
||||
head->metadata.flags = RESHDR_FLAG_METADATA;
|
||||
head->metadata.offset = g_wim_data.wim_align_size + g_wim_data.bin_align_len;
|
||||
head->metadata.size_in_wim = g_wim_data.new_meta_len;
|
||||
head->metadata.raw_size = g_wim_data.new_meta_len;
|
||||
|
||||
head->lookup.flags = 0;
|
||||
head->lookup.offset = head->metadata.offset + g_wim_data.new_meta_align_len;
|
||||
head->lookup.size_in_wim = g_wim_data.new_lookup_len;
|
||||
head->lookup.raw_size = g_wim_data.new_lookup_len;
|
||||
|
||||
grub_file_close(file);
|
||||
|
||||
debug("%s", "windows locate wim finish\n");
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
||||
static grub_uint32_t ventoy_get_override_chunk_num(void)
|
||||
{
|
||||
/* 1: block count in Partition Descriptor */
|
||||
/* 2: file_size in file_entry or extend_file_entry */
|
||||
/* 3: data_size and position in extend data short ad */
|
||||
/* 4: new wim file header */
|
||||
return 4;
|
||||
}
|
||||
|
||||
static void ventoy_windows_fill_override_data( grub_uint64_t isosize, void *override)
|
||||
{
|
||||
grub_uint32_t data32;
|
||||
grub_uint64_t data64;
|
||||
grub_uint64_t sector;
|
||||
grub_uint32_t new_wim_size;
|
||||
ventoy_override_chunk *cur;
|
||||
|
||||
sector = (isosize + 2047) / 2048;
|
||||
|
||||
cur = (ventoy_override_chunk *)override;
|
||||
|
||||
new_wim_size = g_wim_data.wim_align_size + g_wim_data.bin_align_len +
|
||||
g_wim_data.new_meta_align_len + g_wim_data.new_lookup_align_len;
|
||||
|
||||
if (g_wim_data.iso_type == 0)
|
||||
{
|
||||
ventoy_iso9660_override *dirent = (ventoy_iso9660_override *)g_wim_data.override_data;
|
||||
|
||||
dirent->first_sector = (grub_uint32_t)sector;
|
||||
dirent->size = new_wim_size;
|
||||
dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector);
|
||||
dirent->size_be = grub_swap_bytes32(dirent->size);
|
||||
}
|
||||
else
|
||||
{
|
||||
ventoy_udf_override *udf = (ventoy_udf_override *)g_wim_data.override_data;
|
||||
udf->length = new_wim_size;
|
||||
udf->position = (grub_uint32_t)sector - g_wim_data.udf_start_block;
|
||||
}
|
||||
|
||||
//override 1: sector number in pd data
|
||||
cur->img_offset = grub_udf_get_last_pd_size_offset();
|
||||
cur->override_size = 4;
|
||||
data32 = sector - g_wim_data.udf_start_block + (new_wim_size / 2048);
|
||||
grub_memcpy(cur->override_data, &(data32), 4);
|
||||
|
||||
//override 2: filesize in file_entry
|
||||
cur++;
|
||||
cur->img_offset = g_wim_data.fe_entry_size_offset;
|
||||
cur->override_size = 8;
|
||||
data64 = new_wim_size;
|
||||
grub_memcpy(cur->override_data, &(data64), 8);
|
||||
|
||||
/* override 3: position and length in extend data */
|
||||
cur++;
|
||||
cur->img_offset = g_wim_data.override_offset;
|
||||
cur->override_size = g_wim_data.override_len;
|
||||
grub_memcpy(cur->override_data, g_wim_data.override_data, cur->override_size);
|
||||
|
||||
/* override 4: new wim file header */
|
||||
cur++;
|
||||
cur->img_offset = g_wim_data.file_offset;
|
||||
cur->override_size = sizeof(wim_header);
|
||||
grub_memcpy(cur->override_data, &(g_wim_data.wim_header), cur->override_size);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void ventoy_windows_fill_virt_data( grub_uint64_t isosize, ventoy_chain_head *chain)
|
||||
{
|
||||
grub_uint64_t sector;
|
||||
grub_uint32_t offset;
|
||||
grub_uint32_t wim_secs;
|
||||
grub_uint32_t mem_secs;
|
||||
char *override = NULL;
|
||||
ventoy_virt_chunk *cur = NULL;
|
||||
|
||||
sector = (isosize + 2047) / 2048;
|
||||
offset = sizeof(ventoy_virt_chunk);
|
||||
|
||||
wim_secs = g_wim_data.wim_align_size / 2048;
|
||||
mem_secs = (g_wim_data.bin_align_len + g_wim_data.new_meta_align_len + g_wim_data.new_lookup_align_len) / 2048;
|
||||
|
||||
override = (char *)chain + chain->virt_chunk_offset;
|
||||
cur = (ventoy_virt_chunk *)override;
|
||||
|
||||
cur->remap_sector_start = sector;
|
||||
cur->remap_sector_end = cur->remap_sector_start + wim_secs;
|
||||
cur->org_sector_start = (grub_uint32_t)(g_wim_data.file_offset / 2048);
|
||||
|
||||
cur->mem_sector_start = cur->remap_sector_end;
|
||||
cur->mem_sector_end = cur->mem_sector_start + mem_secs;
|
||||
cur->mem_sector_offset = offset;
|
||||
|
||||
grub_memcpy(override + offset, g_wim_data.jump_bin_data, g_wim_data.bin_raw_len);
|
||||
offset += g_wim_data.bin_align_len;
|
||||
|
||||
grub_memcpy(override + offset, g_wim_data.new_meta_data, g_wim_data.new_meta_len);
|
||||
offset += g_wim_data.new_meta_align_len;
|
||||
|
||||
grub_memcpy(override + offset, g_wim_data.new_lookup_data, g_wim_data.new_lookup_len);
|
||||
offset += g_wim_data.new_lookup_align_len;
|
||||
|
||||
chain->virt_img_size_in_bytes += g_wim_data.wim_align_size +
|
||||
g_wim_data.bin_align_len +
|
||||
g_wim_data.new_meta_align_len +
|
||||
g_wim_data.new_lookup_align_len;
|
||||
return;
|
||||
}
|
||||
|
||||
static int ventoy_windows_drive_map(ventoy_chain_head *chain)
|
||||
{
|
||||
grub_disk_t disk;
|
||||
|
||||
debug("drive map begin <%p> ...\n", chain);
|
||||
|
||||
if (chain->disk_drive == 0x80)
|
||||
{
|
||||
disk = grub_disk_open("hd1");
|
||||
if (disk)
|
||||
{
|
||||
grub_disk_close(disk);
|
||||
debug("drive map needed %p\n", disk);
|
||||
chain->drive_map = 0x81;
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("failed to open disk %s\n", "hd1");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("no need to map 0x%x\n", chain->disk_drive);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_windows_chain_data(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
int unknown_image = 0;
|
||||
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_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;
|
||||
|
||||
debug("chain data begin <%s> ...\n", args[0]);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (0 == ventoy_compatible && g_wim_data.new_meta_data == NULL)
|
||||
{
|
||||
unknown_image = 1;
|
||||
debug("Warning: %s was not recognized by Ventoy\n", args[0]);
|
||||
}
|
||||
|
||||
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 || unknown_image)
|
||||
{
|
||||
size = sizeof(ventoy_chain_head) + img_chunk_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
override_size = ventoy_get_override_chunk_num() * sizeof(ventoy_override_chunk);
|
||||
virt_chunk_size = sizeof(ventoy_virt_chunk) + g_wim_data.bin_align_len +
|
||||
g_wim_data.new_meta_align_len + g_wim_data.new_lookup_align_len;;
|
||||
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 */
|
||||
ventoy_fill_os_param(file, &(chain->os_param));
|
||||
|
||||
if (g_wim_data.jump_bin_data && g_wim_data.new_meta_data)
|
||||
{
|
||||
ventoy_update_before_chain(&(chain->os_param), args[0]);
|
||||
}
|
||||
|
||||
/* 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 || unknown_image)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (g_wim_data.new_meta_data == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* part 4: override chunk */
|
||||
chain->override_chunk_offset = chain->img_chunk_offset + img_chunk_size;
|
||||
chain->override_chunk_num = ventoy_get_override_chunk_num();
|
||||
ventoy_windows_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 = 1;
|
||||
ventoy_windows_fill_virt_data(isosize, chain);
|
||||
|
||||
if (ventoy_is_efi_os() == 0)
|
||||
{
|
||||
ventoy_windows_drive_map(chain);
|
||||
}
|
||||
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
14
GenUUID/build.sh
Normal file
@@ -0,0 +1,14 @@
|
||||
#!/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
|
||||
|
50
GenUUID/vtoy_gen_uuid.c
Normal file
@@ -0,0 +1,50 @@
|
||||
/******************************************************************************
|
||||
* 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
After Width: | Height: | Size: 13 KiB |
BIN
ICON/logo_128.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
ICON/logo_16.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
ICON/logo_256.png
Normal file
After Width: | Height: | Size: 76 KiB |
BIN
ICON/logo_32.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
ICON/logo_48.png
Normal file
After Width: | Height: | Size: 5.3 KiB |
BIN
ICON/logo_512.png
Normal file
After Width: | Height: | Size: 223 KiB |
BIN
ICON/logo_64.png
Normal file
After Width: | Height: | Size: 7.7 KiB |
BIN
ICON/logo_72.png
Normal file
After Width: | Height: | Size: 9.0 KiB |
@@ -19,19 +19,25 @@
|
||||
|
||||
. /ventoy/hook/ventoy-hook-lib.sh
|
||||
|
||||
if is_ventoy_hook_finished; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
vtlog "####### $0 $* ########"
|
||||
|
||||
VTPATH_OLD=$PATH; PATH=$BUSYBOX_PATH:$VTOY_PATH/tool:$PATH
|
||||
|
||||
while ! [ -e /dev/null ]; do
|
||||
echo 'xxxxxxxxxx'
|
||||
echo 'xxxxxxxxxx' > /dev/console
|
||||
sleep 1
|
||||
done
|
||||
wait_for_usb_disk_ready
|
||||
|
||||
vtlog "... start inotifyd listen $vtHook ..."
|
||||
$BUSYBOX_PATH/nohup $VTOY_PATH/tool/inotifyd $VTOY_PATH/hook/guix/ventoy-disk.sh /dev:n 2>&- &
|
||||
vtdiskname=$(get_ventoy_disk_name)
|
||||
if [ "$vtdiskname" = "unknown" ]; then
|
||||
vtlog "ventoy disk not found"
|
||||
PATH=$VTPATH_OLD
|
||||
exit 0
|
||||
fi
|
||||
|
||||
ventoy_udev_disk_common_hook "${vtdiskname#/dev/}2" "noreplace"
|
||||
|
||||
PATH=$VTPATH_OLD
|
||||
|
||||
set_ventoy_hook_finish
|
23
IMG/cpio/ventoy/hook/adelie/ventoy-hook.sh
Normal file
@@ -0,0 +1,23 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. $VTOY_PATH/hook/ventoy-os-lib.sh
|
||||
|
||||
$VTOY_PATH/hook/adelie/disk-hook.sh &
|
||||
|
@@ -32,13 +32,14 @@ fi
|
||||
|
||||
#
|
||||
# We do a trick for ATL series here.
|
||||
# Use /dev/loop7 and wapper it as a cdrom with bind mount.
|
||||
# Then the installer will accept /dev/loop7 as the install medium.
|
||||
# Use /dev/vtCheatLoop and wapper it as a cdrom with bind mount.
|
||||
# Then the installer will accept /dev/vtCheatLoop as the install medium.
|
||||
#
|
||||
ventoy_copy_device_mapper /dev/loop7
|
||||
$BUSYBOX_PATH/mkdir -p /tmp/loop7/device/
|
||||
echo 5 > /tmp/loop7/device/type
|
||||
$BUSYBOX_PATH/mount --bind /tmp/loop7 /sys/block/loop7 >> $VTLOG 2>&1
|
||||
vtCheatLoop=loop6
|
||||
ventoy_copy_device_mapper /dev/$vtCheatLoop
|
||||
$BUSYBOX_PATH/mkdir -p /tmp/$vtCheatLoop/device/
|
||||
echo 5 > /tmp/$vtCheatLoop/device/type
|
||||
$BUSYBOX_PATH/mount --bind /tmp/$vtCheatLoop /sys/block/$vtCheatLoop >> $VTLOG 2>&1
|
||||
|
||||
|
||||
# OK finish
|
||||
|
42
IMG/cpio/ventoy/hook/android/ventoy-disk.sh
Normal file
@@ -0,0 +1,42 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. /ventoy/hook/ventoy-hook-lib.sh
|
||||
|
||||
if is_ventoy_hook_finished; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
vtdiskname=$(get_ventoy_disk_name)
|
||||
if [ "$vtdiskname" = "unknown" ]; then
|
||||
vtlog "ventoy disk not found"
|
||||
PATH=$VTPATH_OLD
|
||||
exit 0
|
||||
fi
|
||||
|
||||
ventoy_udev_disk_common_hook "${vtdiskname#/dev/}2" "noreplace"
|
||||
|
||||
if ! [ -e $VTOY_DM_PATH ]; then
|
||||
blkdev_num=$($VTOY_PATH/tool/dmsetup ls | grep ventoy | sed 's/.*(\([0-9][0-9]*\),.*\([0-9][0-9]*\).*/\1 \2/')
|
||||
mknod -m 0666 $VTOY_DM_PATH b $blkdev_num
|
||||
fi
|
||||
|
||||
# OK finish
|
||||
set_ventoy_hook_finish
|
||||
|
27
IMG/cpio/ventoy/hook/android/ventoy-hook.sh
Normal file
@@ -0,0 +1,27 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. $VTOY_PATH/hook/ventoy-os-lib.sh
|
||||
|
||||
if ! [ -d /dev ]; then
|
||||
$BUSYBOX_PATH/mkdir /dev
|
||||
fi
|
||||
|
||||
$SED "1a\export ROOT=/dev/mapper/ventoy" -i /init
|
||||
$SED "/check_root \$device/i\ $BUSYBOX_PATH/sh $VTOY_PATH/hook/android/ventoy-disk.sh" -i /init
|
50
IMG/cpio/ventoy/hook/arch/ovios-disk.sh
Normal file
@@ -0,0 +1,50 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. /ventoy/hook/ventoy-hook-lib.sh
|
||||
|
||||
vtlog "######### $0 $* ############"
|
||||
|
||||
VTPATH_OLD=$PATH; PATH=$BUSYBOX_PATH:$VTOY_PATH/tool:$PATH
|
||||
|
||||
wait_for_usb_disk_ready
|
||||
|
||||
vtdiskname=$(get_ventoy_disk_name)
|
||||
if [ "$vtdiskname" = "unknown" ]; then
|
||||
vtlog "ventoy disk not found"
|
||||
PATH=$VTPATH_OLD
|
||||
exit 0
|
||||
fi
|
||||
|
||||
ventoy_udev_disk_common_hook "${vtdiskname#/dev/}2" "noreplace"
|
||||
|
||||
blkdev_num=$($VTOY_PATH/tool/dmsetup ls | grep ventoy | sed 's/.*(\([0-9][0-9]*\),.*\([0-9][0-9]*\).*/\1:\2/')
|
||||
blkdev_num_mknod=$($VTOY_PATH/tool/dmsetup ls | grep ventoy | sed 's/.*(\([0-9][0-9]*\),.*\([0-9][0-9]*\).*/\1 \2/')
|
||||
vtDM=$(ventoy_find_dm_id ${blkdev_num})
|
||||
|
||||
vtlog "blkdev_num=$blkdev_num blkdev_num_mknod=$blkdev_num_mknod vtDM=$vtDM"
|
||||
|
||||
if [ -b /dev/$vtDM ]; then
|
||||
vtlog "dev already exist ..."
|
||||
else
|
||||
vtlog "mknode dev ..."
|
||||
mknod -m 660 /dev/$vtDM b $blkdev_num_mknod
|
||||
fi
|
||||
|
||||
PATH=$VTPATH_OLD
|
@@ -22,6 +22,18 @@
|
||||
if $GREP -q '^"$mount_handler"' /init; then
|
||||
echo 'use mount_handler ...' >> $VTLOG
|
||||
$SED "/^\"\$mount_handler\"/i\ $BUSYBOX_PATH/sh $VTOY_PATH/hook/arch/ventoy-disk.sh \"\$archisodevice\"" -i /init
|
||||
|
||||
if [ -f /hooks/archiso ]; then
|
||||
$SED '/while ! poll_device "${dev}"/a\ if /ventoy/busybox/sh /ventoy/hook/arch/ventoy-timeout.sh ${dev}; then break; fi' -i /hooks/archiso
|
||||
fi
|
||||
elif $GREP -q '^KEEP_SEARCHING' /init; then
|
||||
echo 'KEEP_SEARCHING found ...' >> $VTLOG
|
||||
$SED "/^KEEP_SEARCHING/i\ $BUSYBOX_PATH/sh $VTOY_PATH/hook/arch/ovios-disk.sh " -i /init
|
||||
|
||||
$BUSYBOX_PATH/mkdir -p /dev
|
||||
$BUSYBOX_PATH/mkdir -p /sys
|
||||
$BUSYBOX_PATH/mount -t sysfs sys /sys
|
||||
|
||||
else
|
||||
# some archlinux initramfs doesn't contain device-mapper udev rules file
|
||||
ARCH_UDEV_DIR=$(ventoy_get_udev_conf_dir)
|
||||
|
36
IMG/cpio/ventoy/hook/arch/ventoy-timeout.sh
Normal file
@@ -0,0 +1,36 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. /ventoy/hook/ventoy-hook-lib.sh
|
||||
|
||||
vtlog "######### $0 $* ############"
|
||||
|
||||
blkdev_num=$($VTOY_PATH/tool/dmsetup ls | grep ventoy | sed 's/.*(\([0-9][0-9]*\),.*\([0-9][0-9]*\).*/\1:\2/')
|
||||
vtDM=$(ventoy_find_dm_id ${blkdev_num})
|
||||
|
||||
if [ -b /dev/$vtDM ]; then
|
||||
vtlog "ln -s /dev/$vtDM $1"
|
||||
ln -s /dev/$vtDM "$1"
|
||||
exit 0
|
||||
else
|
||||
vtlog "Device-mapper not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
47
IMG/cpio/ventoy/hook/cdlinux/disk-hook.sh
Normal file
@@ -0,0 +1,47 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. /ventoy/hook/ventoy-hook-lib.sh
|
||||
|
||||
if is_ventoy_hook_finished; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
vtlog "####### $0 $* ########"
|
||||
|
||||
VTPATH_OLD=$PATH; PATH=$BUSYBOX_PATH:$VTOY_PATH/tool:$PATH
|
||||
|
||||
wait_for_usb_disk_ready
|
||||
|
||||
vtdiskname=$(get_ventoy_disk_name)
|
||||
if [ "$vtdiskname" = "unknown" ]; then
|
||||
vtlog "ventoy disk not found"
|
||||
PATH=$VTPATH_OLD
|
||||
exit 0
|
||||
fi
|
||||
|
||||
ventoy_udev_disk_common_hook "${vtdiskname#/dev/}2" "noreplace"
|
||||
|
||||
blkdev_num=$($VTOY_PATH/tool/dmsetup ls | grep ventoy | sed 's/.*(\([0-9][0-9]*\),.*\([0-9][0-9]*\).*/\1 \2/')
|
||||
mknod -m 0666 /dev/ventoy b $blkdev_num
|
||||
|
||||
|
||||
PATH=$VTPATH_OLD
|
||||
|
||||
set_ventoy_hook_finish
|
43
IMG/cpio/ventoy/hook/cdlinux/ventoy-hook.sh
Normal file
@@ -0,0 +1,43 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. $VTOY_PATH/hook/ventoy-os-lib.sh
|
||||
|
||||
echo "CDlinux process..." >> $VTLOG
|
||||
|
||||
$BUSYBOX_PATH/mknod -m 0660 /ventoy/ram0 b 1 0
|
||||
|
||||
$BUSYBOX_PATH/mkdir /vtmnt /ventoy_rdroot
|
||||
$BUSYBOX_PATH/mount -t squashfs /ventoy/ram0 /vtmnt
|
||||
|
||||
$BUSYBOX_PATH/mount -nt tmpfs -o mode=755 tmpfs /ventoy_rdroot
|
||||
|
||||
$BUSYBOX_PATH/cp -a /vtmnt/* /ventoy_rdroot
|
||||
$BUSYBOX_PATH/ls -1a /vtmnt/ | $GREP '^\.[^.]' | while read vtLine; do
|
||||
$BUSYBOX_PATH/cp -a /vtmnt/$vtLine /ventoy_rdroot
|
||||
done
|
||||
|
||||
$BUSYBOX_PATH/umount /vtmnt && $BUSYBOX_PATH/rm -rf /vtmnt
|
||||
$BUSYBOX_PATH/cp -a /ventoy /ventoy_rdroot
|
||||
|
||||
echo 'echo "CDL_DEV=/dev/mapper/ventoy" >>"$VAR_FILE"' >> /ventoy_rdroot/etc/rc.d/rc.var
|
||||
|
||||
ventoy_set_rule_dir_prefix /ventoy_rdroot
|
||||
ventoy_systemd_udevd_work_around
|
||||
ventoy_add_udev_rule "$VTOY_PATH/hook/default/udev_disk_hook.sh %k noreplace"
|