mirror of
https://github.com/ventoy/Ventoy.git
synced 2025-09-16 09:01:15 +00:00
Compare commits
95 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
d678e54956 | ||
|
8dce0adda6 | ||
|
1bf3e73373 | ||
|
a9996d6761 | ||
|
dafea731c8 | ||
|
6d093e88e7 | ||
|
58a93cdb40 | ||
|
9962775296 | ||
|
062f816020 | ||
|
89b7232b76 | ||
|
1186caba41 | ||
|
be50ea69aa | ||
|
433d854aab | ||
|
4cb9134e5c | ||
|
faceaf4267 | ||
|
37edd5a349 | ||
|
ed0f8721d7 | ||
|
d80a008c04 | ||
|
036e9cc167 | ||
|
26258653b7 | ||
|
754e754412 | ||
|
5af01de7c2 | ||
|
f9763a44b2 | ||
|
d063dbb7f2 | ||
|
89938e3c78 | ||
|
85840f626b | ||
|
7d1507906d | ||
|
0f8478fbe1 | ||
|
a6d3ecc7a9 | ||
|
5817b8b7b0 | ||
|
8493715fb4 | ||
|
3c46432d6f | ||
|
88dcceeabc | ||
|
ef204263ad | ||
|
e08e6705cf | ||
|
a8b2fdccc7 | ||
|
85348956df | ||
|
aa0a2ed067 | ||
|
49ceaa0f61 | ||
|
23986d742d | ||
|
039e68400d | ||
|
e384dad4d0 | ||
|
dcb3264519 | ||
|
4fda20d844 | ||
|
b32cf97f1f | ||
|
f7b35f371b | ||
|
49ca1e05a4 | ||
|
9ecbff9ce6 | ||
|
1d034f0a24 | ||
|
0ddc76a3aa | ||
|
a1ddade13c | ||
|
b925bbdeec | ||
|
e91b315f09 | ||
|
1cbe4c81b4 | ||
|
42990058ed | ||
|
171667c547 | ||
|
a5c706511b | ||
|
785255b65f | ||
|
176c819d10 | ||
|
8f2bf03084 | ||
|
4408be5cf0 | ||
|
74154ad9a3 | ||
|
43fcd4f262 | ||
|
be35990666 | ||
|
ad3db3dfcb | ||
|
227264f208 | ||
|
1f37663285 | ||
|
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
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']
|
24
.github/workflows/ci.yml
vendored
Normal file
24
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
name: Ventoy CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Run docker-compose up
|
||||
run: docker-compose up
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ventoy-linux
|
||||
path: INSTALL/ventoy-*linux*
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ventoy-windows
|
||||
path: INSTALL/ventoy-*windows*
|
||||
|
1166
BUSYBOX/64h.config
Normal file
1166
BUSYBOX/64h.config
Normal file
File diff suppressed because it is too large
Load Diff
18
BUSYBOX/chmod/build.sh
Normal file
18
BUSYBOX/chmod/build.sh
Normal file
@@ -0,0 +1,18 @@
|
||||
#!/bin/sh
|
||||
|
||||
DSTDIR=../../IMG/cpio/ventoy/busybox
|
||||
|
||||
rm -f vtchmod32 vtchmod64
|
||||
rm -f $DSTDIR/vtchmod32 $DSTDIR/vtchmod64
|
||||
|
||||
/opt/diet32/bin/diet gcc -Os -m32 vtchmod.c -o vtchmod32
|
||||
/opt/diet64/bin/diet gcc -Os vtchmod.c -o vtchmod64
|
||||
|
||||
chmod 777 vtchmod32
|
||||
chmod 777 vtchmod64
|
||||
|
||||
cp -a vtchmod32 $DSTDIR/
|
||||
cp -a vtchmod64 $DSTDIR/
|
||||
|
||||
|
||||
|
13
BUSYBOX/chmod/vtchmod.c
Normal file
13
BUSYBOX/chmod/vtchmod.c
Normal file
@@ -0,0 +1,13 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc != 2)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return chmod(argv[1], 0777);
|
||||
}
|
||||
|
BIN
BUSYBOX/chmod/vtchmod32
Normal file
BIN
BUSYBOX/chmod/vtchmod32
Normal file
Binary file not shown.
BIN
BUSYBOX/chmod/vtchmod64
Normal file
BIN
BUSYBOX/chmod/vtchmod64
Normal file
Binary file not shown.
@@ -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
|
||||
@@ -27,4 +28,22 @@ build for 32bit, static linked with dietlibc
|
||||
|
||||
4. make
|
||||
5. strip dmsetup/dmsetup
|
||||
5. get dmsetup/dmsetup as the binary file
|
||||
6. get dmsetup/dmsetup as the dmsetup32 binary file
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
======================== Build for 64bit dmsetup =========================
|
||||
https://www.uclibc.org/downloads/binaries/0.9.30.1/mini-native-x86_64.tar.bz2
|
||||
1. extract device mapper source code
|
||||
2. extract mini-native-x86_64.tar.bz2
|
||||
3. chroot to mini-native-x86_64
|
||||
3. ./configure --disable-nls --disable-selinux --disable-shared --enable-static_link
|
||||
4. make
|
||||
5. strip dmsetup/dmsetup.static
|
||||
6. get dmsetup/dmsetup.static as the dmsetup64 binary file
|
||||
|
||||
|
||||
|
||||
|
BIN
DMSETUP/dmsetup64
Normal file
BIN
DMSETUP/dmsetup64
Normal file
Binary file not shown.
228
DOC/BuildVentoyFromSource.txt
Normal file
228
DOC/BuildVentoyFromSource.txt
Normal file
@@ -0,0 +1,228 @@
|
||||
|
||||
==========================================
|
||||
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 xzminidec32 ==
|
||||
cd /home/Ventoy-master/Ventoy2Disk/Ventoy2Disk/xz-embedded-20130513/userspace
|
||||
make -f ventoy_makefile
|
||||
strip --strip-all xzminidec
|
||||
|
||||
4.16 == Build xzminidec64 ==
|
||||
cd /home/Ventoy-master/Ventoy2Disk/Ventoy2Disk/xz-embedded-20130513/userspace
|
||||
make -f ventoy_makefile64
|
||||
strip --strip-all xzminidec
|
||||
|
||||
4.17 == Build iso9660_x64.efi ==
|
||||
This efi driver is from https://github.com/pbatard/efifs
|
||||
Follow all the build instructions in this project. I modified 3 files (the original and modified source are at /home/Ventoy-master/EDK2/efiffs)
|
||||
|
||||
4.18 IMG/cpio/ventoy/busybox/64h
|
||||
https://www.uclibc.org/downloads/binaries/0.9.30.1/mini-native-x86_64.tar.bz2
|
||||
https://busybox.net/downloads/busybox-1.32.0.tar.bz2
|
||||
use BUSYBOX/64h.config and uclibc to build busybox-1.32
|
||||
|
||||
4.19 == Build lunzip32/lunzip64 ==
|
||||
http://mirror.yongbok.net/nongnu/lzip/lunzip/lunzip-1.11.tar.gz
|
||||
PATH=$PATH:/opt/diet/bin
|
||||
./configure --disable-nls CC='diet gcc -nostdinc'
|
||||
make
|
||||
strip --strip-all lunzip
|
||||
|
||||
|
||||
|
||||
==========================================
|
||||
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/ash
|
||||
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
|
||||
|
||||
|
||||
|
29
DOC/LoopExBuild.txt
Normal file
29
DOC/LoopExBuild.txt
Normal file
@@ -0,0 +1,29 @@
|
||||
|
||||
1. LAKKA dm-mod.ko
|
||||
LaKKa config
|
||||
https://github.com/libretro/Lakka-LibreELEC/releases download source code
|
||||
\projects\Generic\linux\linux.x86_64.conf
|
||||
|
||||
Linux Kernel
|
||||
linux-4.11.12.tar.xz & patch-4.11.12-rt14.patch.xz
|
||||
patch -p1 < ../patch-4.11.12-rt14
|
||||
|
||||
make menuconfig
|
||||
select device mapper as module
|
||||
make -j 16
|
||||
get drivers\md\dm-mod.ko
|
||||
|
||||
2. LibreELEC dm-mod.ko
|
||||
LibreELEC config
|
||||
https://github.com/LibreELEC/LibreELEC.tv/releases download source code
|
||||
\projects\Generic\linux\linux.x86_64.conf
|
||||
|
||||
Linux Kernel
|
||||
linux-5.1.6.tar.xz
|
||||
make menuconfig
|
||||
select device mapper as module
|
||||
make -j 16
|
||||
get drivers\md\dm-mod.ko
|
||||
|
||||
|
||||
|
34
DOC/installdietlibc.sh
Normal file
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
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
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
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -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__)
|
||||
@@ -217,7 +227,9 @@ if (gDebugPrint) \
|
||||
gBS->WaitForEvent(1, &gST->ConIn->WaitForKey, &__Index);\
|
||||
}
|
||||
|
||||
typedef int (*grub_env_set_pf)(const char *name, const char *val);
|
||||
typedef const char * (*grub_env_get_pf)(const char *name);
|
||||
typedef int (*grub_env_printf_pf)(const char *fmt, ...);
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
@@ -244,8 +256,9 @@ typedef struct ventoy_grub_param_file_replace
|
||||
typedef struct ventoy_grub_param
|
||||
{
|
||||
grub_env_get_pf grub_env_get;
|
||||
|
||||
grub_env_set_pf grub_env_set;
|
||||
ventoy_grub_param_file_replace file_replace;
|
||||
grub_env_printf_pf grub_env_printf;
|
||||
}ventoy_grub_param;
|
||||
|
||||
typedef struct ventoy_ram_disk
|
||||
@@ -254,6 +267,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 +294,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 +315,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 +327,39 @@ EFI_STATUS EFIAPI ventoy_block_io_read
|
||||
OUT VOID *Buffer
|
||||
);
|
||||
|
||||
|
||||
extern ventoy_chain_head *g_chain;
|
||||
extern ventoy_img_chunk *g_chunk;
|
||||
extern UINT32 g_img_chunk_num;
|
||||
extern ventoy_override_chunk *g_override_chunk;
|
||||
extern UINT32 g_override_chunk_num;
|
||||
extern ventoy_virt_chunk *g_virt_chunk;
|
||||
extern UINT32 g_virt_chunk_num;
|
||||
extern vtoy_block_data gBlockData;
|
||||
extern ventoy_efi_file_replace g_efi_file_replace;
|
||||
extern ventoy_sector_flag *g_sector_flag;
|
||||
extern UINT32 g_sector_flag_num;
|
||||
extern BOOLEAN gMemdiskMode;
|
||||
extern BOOLEAN gSector512Mode;
|
||||
extern UINTN g_iso_buf_size;
|
||||
extern UINT8 *g_iso_data_buf;
|
||||
extern ventoy_grub_param_file_replace *g_file_replace_list;
|
||||
extern BOOLEAN g_fixup_iso9660_secover_enable;
|
||||
extern EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *g_con_simple_input_ex;
|
||||
extern BOOLEAN g_fix_windows_1st_cdrom_issue;
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_wrapper_open_volume
|
||||
(
|
||||
IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
|
||||
OUT EFI_FILE_PROTOCOL **Root
|
||||
);
|
||||
EFI_STATUS EFIAPI ventoy_install_blockio(IN EFI_HANDLE ImageHandle, IN UINT64 ImgSize);
|
||||
EFI_STATUS EFIAPI ventoy_wrapper_push_openvolume(IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME OpenVolume);
|
||||
EFI_STATUS ventoy_hook_keyboard_start(VOID);
|
||||
EFI_STATUS ventoy_hook_keyboard_stop(VOID);
|
||||
BOOLEAN ventoy_is_cdrom_dp_exist(VOID);
|
||||
EFI_STATUS ventoy_hook_1st_cdrom_start(VOID);
|
||||
EFI_STATUS ventoy_hook_1st_cdrom_stop(VOID);
|
||||
|
||||
#endif
|
||||
|
@@ -29,6 +29,7 @@
|
||||
Ventoy.h
|
||||
Ventoy.c
|
||||
VentoyDebug.c
|
||||
VentoyProtocol.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
@@ -36,6 +36,10 @@
|
||||
#include <Protocol/SimpleFileSystem.h>
|
||||
#include <Ventoy.h>
|
||||
|
||||
#define PROCOTOL_SLEEP_MSECONDS 0
|
||||
|
||||
#define debug_sleep() if (PROCOTOL_SLEEP_MSECONDS) gBS->Stall(1000 * PROCOTOL_SLEEP_MSECONDS)
|
||||
|
||||
STATIC ventoy_system_wrapper g_system_wrapper;
|
||||
|
||||
static struct well_known_guid g_efi_well_known_guids[] =
|
||||
@@ -84,183 +88,6 @@ static const char * ventoy_get_guid_name(EFI_GUID *guid)
|
||||
return gEfiGuidName;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_fs_open(EFI_FILE_HANDLE This, EFI_FILE_HANDLE *New, CHAR16 *Name, UINT64 Mode, UINT64 Attributes)
|
||||
{
|
||||
(VOID)This;
|
||||
(VOID)New;
|
||||
(VOID)Name;
|
||||
(VOID)Mode;
|
||||
(VOID)Attributes;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_open_ex(EFI_FILE_HANDLE This, EFI_FILE_HANDLE *New, CHAR16 *Name, UINT64 Mode, UINT64 Attributes, EFI_FILE_IO_TOKEN *Token)
|
||||
{
|
||||
return ventoy_wrapper_fs_open(This, New, Name, Mode, Attributes);
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_delete(EFI_FILE_HANDLE This)
|
||||
{
|
||||
(VOID)This;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_set_info(EFI_FILE_HANDLE This, EFI_GUID *Type, UINTN Len, VOID *Data)
|
||||
{
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_flush(EFI_FILE_HANDLE This)
|
||||
{
|
||||
(VOID)This;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/* Ex version */
|
||||
EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_flush_ex(EFI_FILE_HANDLE This, EFI_FILE_IO_TOKEN *Token)
|
||||
{
|
||||
(VOID)This;
|
||||
(VOID)Token;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_write(EFI_FILE_HANDLE This, UINTN *Len, VOID *Data)
|
||||
{
|
||||
(VOID)This;
|
||||
(VOID)Len;
|
||||
(VOID)Data;
|
||||
|
||||
return EFI_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_write_ex(IN EFI_FILE_PROTOCOL *This, IN OUT EFI_FILE_IO_TOKEN *Token)
|
||||
{
|
||||
return ventoy_wrapper_file_write(This, &(Token->BufferSize), Token->Buffer);
|
||||
}
|
||||
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_close(EFI_FILE_HANDLE This)
|
||||
{
|
||||
(VOID)This;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_set_pos(EFI_FILE_HANDLE This, UINT64 Position)
|
||||
{
|
||||
(VOID)This;
|
||||
|
||||
g_efi_file_replace.CurPos = Position;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_get_pos(EFI_FILE_HANDLE This, UINT64 *Position)
|
||||
{
|
||||
(VOID)This;
|
||||
|
||||
*Position = g_efi_file_replace.CurPos;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_get_info(EFI_FILE_HANDLE This, EFI_GUID *Type, UINTN *Len, VOID *Data)
|
||||
{
|
||||
EFI_FILE_INFO *Info = (EFI_FILE_INFO *) Data;
|
||||
|
||||
debug("ventoy_wrapper_file_get_info ... %u", *Len);
|
||||
|
||||
if (!CompareGuid(Type, &gEfiFileInfoGuid))
|
||||
{
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (*Len == 0)
|
||||
{
|
||||
*Len = 384;
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
ZeroMem(Data, sizeof(EFI_FILE_INFO));
|
||||
|
||||
Info->Size = sizeof(EFI_FILE_INFO);
|
||||
Info->FileSize = g_efi_file_replace.FileSizeBytes;
|
||||
Info->PhysicalSize = g_efi_file_replace.FileSizeBytes;
|
||||
Info->Attribute = EFI_FILE_READ_ONLY;
|
||||
//Info->FileName = EFI_FILE_READ_ONLY;
|
||||
|
||||
*Len = Info->Size;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_read(EFI_FILE_HANDLE This, UINTN *Len, VOID *Data)
|
||||
{
|
||||
EFI_LBA Lba;
|
||||
UINTN ReadLen = *Len;
|
||||
|
||||
(VOID)This;
|
||||
|
||||
debug("ventoy_wrapper_file_read ... %u", *Len);
|
||||
|
||||
if (g_efi_file_replace.CurPos + ReadLen > g_efi_file_replace.FileSizeBytes)
|
||||
{
|
||||
ReadLen = g_efi_file_replace.FileSizeBytes - g_efi_file_replace.CurPos;
|
||||
}
|
||||
|
||||
Lba = g_efi_file_replace.CurPos / 2048 + g_efi_file_replace.BlockIoSectorStart;
|
||||
|
||||
ventoy_block_io_read(NULL, 0, Lba, ReadLen, Data);
|
||||
|
||||
*Len = ReadLen;
|
||||
|
||||
g_efi_file_replace.CurPos += ReadLen;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_read_ex(IN EFI_FILE_PROTOCOL *This, IN OUT EFI_FILE_IO_TOKEN *Token)
|
||||
{
|
||||
return ventoy_wrapper_file_read(This, &(Token->BufferSize), Token->Buffer);
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_wrapper_file_procotol(EFI_FILE_PROTOCOL *File)
|
||||
{
|
||||
File->Revision = EFI_FILE_PROTOCOL_REVISION2;
|
||||
File->Open = ventoy_wrapper_fs_open;
|
||||
File->Close = ventoy_wrapper_file_close;
|
||||
File->Delete = ventoy_wrapper_file_delete;
|
||||
File->Read = ventoy_wrapper_file_read;
|
||||
File->Write = ventoy_wrapper_file_write;
|
||||
File->GetPosition = ventoy_wrapper_file_get_pos;
|
||||
File->SetPosition = ventoy_wrapper_file_set_pos;
|
||||
File->GetInfo = ventoy_wrapper_file_get_info;
|
||||
File->SetInfo = ventoy_wrapper_file_set_info;
|
||||
File->Flush = ventoy_wrapper_file_flush;
|
||||
File->OpenEx = ventoy_wrapper_file_open_ex;
|
||||
File->ReadEx = ventoy_wrapper_file_read_ex;
|
||||
File->WriteEx = ventoy_wrapper_file_write_ex;
|
||||
File->FlushEx = ventoy_wrapper_file_flush_ex;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
STATIC EFI_STATUS EFIAPI ventoy_handle_protocol
|
||||
(
|
||||
IN EFI_HANDLE Handle,
|
||||
@@ -270,7 +97,7 @@ STATIC EFI_STATUS EFIAPI ventoy_handle_protocol
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
|
||||
debug("ventoy_handle_protocol:%a", ventoy_get_guid_name(Protocol));
|
||||
debug("ventoy_handle_protocol:%a", ventoy_get_guid_name(Protocol)); debug_sleep();
|
||||
Status = g_system_wrapper.OriHandleProtocol(Handle, Protocol, Interface);
|
||||
|
||||
if (CompareGuid(Protocol, &gEfiSimpleFileSystemProtocolGuid))
|
||||
@@ -280,7 +107,7 @@ STATIC EFI_STATUS EFIAPI ventoy_handle_protocol
|
||||
|
||||
pFile->OpenVolume(pFile, &FileProtocol);
|
||||
|
||||
debug("Handle FS Protocol: %p OpenVolume:%p, FileProtocol:%p, Open:%p",
|
||||
trace("Handle FS Protocol: %p OpenVolume:%p, FileProtocol:%p, Open:%p",
|
||||
pFile, pFile->OpenVolume, FileProtocol, FileProtocol->Open);
|
||||
|
||||
sleep(3);
|
||||
@@ -299,7 +126,7 @@ STATIC EFI_STATUS EFIAPI ventoy_open_protocol
|
||||
IN UINT32 Attributes
|
||||
)
|
||||
{
|
||||
debug("ventoy_open_protocol:%a", ventoy_get_guid_name(Protocol));
|
||||
debug("ventoy_open_protocol:<%p> %a", Handle, ventoy_get_guid_name(Protocol)); debug_sleep();
|
||||
return g_system_wrapper.OriOpenProtocol(Handle, Protocol, Interface, AgentHandle, ControllerHandle, Attributes);
|
||||
}
|
||||
|
||||
@@ -310,15 +137,91 @@ STATIC EFI_STATUS EFIAPI ventoy_locate_protocol
|
||||
OUT VOID **Interface
|
||||
)
|
||||
{
|
||||
debug("ventoy_locate_protocol:%a", ventoy_get_guid_name(Protocol));
|
||||
debug("ventoy_locate_protocol:%a", ventoy_get_guid_name(Protocol)); debug_sleep();
|
||||
return g_system_wrapper.OriLocateProtocol(Protocol, Registration, Interface);
|
||||
}
|
||||
|
||||
STATIC EFI_STATUS EFIAPI ventoy_locate_handle_buffer
|
||||
(
|
||||
IN EFI_LOCATE_SEARCH_TYPE SearchType,
|
||||
IN EFI_GUID *Protocol, OPTIONAL
|
||||
IN VOID *SearchKey, OPTIONAL
|
||||
IN OUT UINTN *NoHandles,
|
||||
OUT EFI_HANDLE **Buffer
|
||||
)
|
||||
{
|
||||
debug("ventoy_locate_handle_buffer:%a", ventoy_get_guid_name(Protocol)); debug_sleep();
|
||||
return g_system_wrapper.OriLocateHandleBuffer(SearchType, Protocol, SearchKey, NoHandles, Buffer);
|
||||
}
|
||||
|
||||
STATIC EFI_STATUS EFIAPI ventoy_protocol_per_handle
|
||||
(
|
||||
IN EFI_HANDLE Handle,
|
||||
OUT EFI_GUID ***ProtocolBuffer,
|
||||
OUT UINTN *ProtocolBufferCount
|
||||
)
|
||||
{
|
||||
debug("ventoy_protocol_per_handle:%p", Handle); debug_sleep();
|
||||
return g_system_wrapper.OriProtocolsPerHandle(Handle, ProtocolBuffer, ProtocolBufferCount);
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_locate_handle
|
||||
(
|
||||
IN EFI_LOCATE_SEARCH_TYPE SearchType,
|
||||
IN EFI_GUID *Protocol, OPTIONAL
|
||||
IN VOID *SearchKey, OPTIONAL
|
||||
IN OUT UINTN *BufferSize,
|
||||
OUT EFI_HANDLE *Buffer
|
||||
)
|
||||
{
|
||||
UINTN i;
|
||||
EFI_HANDLE Handle;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
|
||||
debug("ventoy_locate_handle: %d %a %p", SearchType, ventoy_get_guid_name(Protocol), SearchKey);
|
||||
Status = g_system_wrapper.OriLocateHandle(SearchType, Protocol, SearchKey, BufferSize, Buffer);
|
||||
debug("ventoy_locate_handle: %r Handle Count:%u", Status, *BufferSize/sizeof(EFI_HANDLE));
|
||||
|
||||
if (EFI_SUCCESS == Status)
|
||||
{
|
||||
for (i = 0; i < *BufferSize / sizeof(EFI_HANDLE); i++)
|
||||
{
|
||||
if (Buffer[i] == gBlockData.Handle)
|
||||
{
|
||||
Handle = Buffer[0];
|
||||
Buffer[0] = Buffer[i];
|
||||
Buffer[i] = Handle;
|
||||
debug("####### Handle at %u", i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
debug_sleep();
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
STATIC EFI_STATUS EFIAPI ventoy_locate_device_path
|
||||
(
|
||||
IN EFI_GUID *Protocol,
|
||||
IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,
|
||||
OUT EFI_HANDLE *Device
|
||||
)
|
||||
{
|
||||
debug("ventoy_locate_device_path:%a", ventoy_get_guid_name(Protocol)); debug_sleep();
|
||||
return g_system_wrapper.OriLocateDevicePath(Protocol, DevicePath, Device);
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_wrapper_system(VOID)
|
||||
{
|
||||
ventoy_wrapper(gBS, g_system_wrapper, LocateProtocol, ventoy_locate_protocol);
|
||||
ventoy_wrapper(gBS, g_system_wrapper, HandleProtocol, ventoy_handle_protocol);
|
||||
ventoy_wrapper(gBS, g_system_wrapper, OpenProtocol, ventoy_open_protocol);
|
||||
ventoy_wrapper(gBS, g_system_wrapper, LocateProtocol, ventoy_locate_protocol);
|
||||
ventoy_wrapper(gBS, g_system_wrapper, HandleProtocol, ventoy_handle_protocol);
|
||||
ventoy_wrapper(gBS, g_system_wrapper, OpenProtocol, ventoy_open_protocol);
|
||||
ventoy_wrapper(gBS, g_system_wrapper, LocateHandleBuffer, ventoy_locate_handle_buffer);
|
||||
ventoy_wrapper(gBS, g_system_wrapper, ProtocolsPerHandle, ventoy_protocol_per_handle);
|
||||
ventoy_wrapper(gBS, g_system_wrapper, LocateHandle, ventoy_locate_handle);
|
||||
ventoy_wrapper(gBS, g_system_wrapper, LocateDevicePath, ventoy_locate_device_path);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,179 @@
|
||||
/******************************************************************************
|
||||
* Memhole.c
|
||||
*
|
||||
* Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Uefi.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/PrintLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DevicePathLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||
#include <Library/UefiApplicationEntryPoint.h>
|
||||
#include <Protocol/LoadedImage.h>
|
||||
#include <Guid/FileInfo.h>
|
||||
#include <Guid/FileSystemInfo.h>
|
||||
#include <Protocol/BlockIo.h>
|
||||
#include <Protocol/RamDisk.h>
|
||||
#include <Protocol/SimpleFileSystem.h>
|
||||
#include <VtoyUtil.h>
|
||||
|
||||
STATIC BOOLEAN IsMemContiguous
|
||||
(
|
||||
IN CONST EFI_MEMORY_DESCRIPTOR *Prev,
|
||||
IN CONST EFI_MEMORY_DESCRIPTOR *Curr,
|
||||
IN CONST EFI_MEMORY_DESCRIPTOR *Next
|
||||
)
|
||||
{
|
||||
UINTN Addr1 = 0;
|
||||
UINTN Addr2 = 0;
|
||||
|
||||
if (Prev == NULL || Curr == NULL || Next == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (Prev->Type == EfiBootServicesData &&
|
||||
Curr->Type == EfiConventionalMemory &&
|
||||
Next->Type == EfiBootServicesData)
|
||||
{
|
||||
Addr1 = Prev->PhysicalStart + MultU64x64(SIZE_4KB, Prev->NumberOfPages);
|
||||
Addr2 = Curr->PhysicalStart + MultU64x64(SIZE_4KB, Curr->NumberOfPages);
|
||||
|
||||
if (Addr1 == Curr->PhysicalStart && Addr2 == Next->PhysicalStart)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
STATIC EFI_MEMORY_DESCRIPTOR* GetMemDesc
|
||||
(
|
||||
OUT UINTN *pSize,
|
||||
OUT UINTN *pItemSize,
|
||||
OUT UINTN *pDescCount
|
||||
)
|
||||
{
|
||||
UINTN Size = 0;
|
||||
UINTN MapKey = 0;
|
||||
UINTN ItemSize = 0;
|
||||
UINTN DescCount = 0;
|
||||
UINT32 Version = 0;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_MEMORY_DESCRIPTOR *pDesc = NULL;
|
||||
EFI_MEMORY_DESCRIPTOR *Curr = NULL;
|
||||
|
||||
Status = gBS->GetMemoryMap(&Size, pDesc, &MapKey, &ItemSize, &Version);
|
||||
if (EFI_BUFFER_TOO_SMALL != Status)
|
||||
{
|
||||
debug("GetMemoryMap: %r", Status);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Size += SIZE_1KB;
|
||||
pDesc = AllocatePool(Size);
|
||||
if (!pDesc)
|
||||
{
|
||||
debug("AllocatePool: %lu failed", Size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ZeroMem(pDesc, Size);
|
||||
|
||||
Status = gBS->GetMemoryMap(&Size, pDesc, &MapKey, &ItemSize, &Version);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
debug("GetMemoryMap: %r", Status);
|
||||
FreePool(pDesc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Curr = pDesc;
|
||||
while (Curr && Curr < (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)pDesc + Size))
|
||||
{
|
||||
DescCount++;
|
||||
Curr = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)Curr + ItemSize);
|
||||
}
|
||||
|
||||
*pSize = Size;
|
||||
*pItemSize = ItemSize;
|
||||
*pDescCount = DescCount;
|
||||
|
||||
debug("GetMemoryMap: ItemSize:%lu Count:%lu", ItemSize, DescCount);
|
||||
|
||||
return pDesc;
|
||||
}
|
||||
|
||||
EFI_STATUS FixWindowsMemhole(IN EFI_HANDLE ImageHandle, IN CONST CHAR16 *CmdLine)
|
||||
{
|
||||
UINTN Size = 0;
|
||||
UINTN ItemSize = 0;
|
||||
UINTN DescCount = 0;
|
||||
UINTN TotalMem = 0;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_PHYSICAL_ADDRESS AllocAddr = 0;
|
||||
EFI_MEMORY_DESCRIPTOR *pDescs = NULL;
|
||||
EFI_MEMORY_DESCRIPTOR *Prev = NULL;
|
||||
EFI_MEMORY_DESCRIPTOR *Next = NULL;
|
||||
EFI_MEMORY_DESCRIPTOR *Curr = NULL;
|
||||
|
||||
(VOID)ImageHandle;
|
||||
(VOID)CmdLine;
|
||||
|
||||
pDescs = GetMemDesc(&Size, &ItemSize, &DescCount);
|
||||
if (!pDescs)
|
||||
{
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (DescCount < 500)
|
||||
{
|
||||
FreePool(pDescs);
|
||||
Printf("There is no need to fixup (%lu)\n", DescCount);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
Curr = pDescs;
|
||||
while ((UINT8 *)Curr < (UINT8 *)pDescs + Size)
|
||||
{
|
||||
Next = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)Curr + ItemSize);
|
||||
|
||||
if (IsMemContiguous(Prev, Curr, Next))
|
||||
{
|
||||
AllocAddr = Curr->PhysicalStart;
|
||||
Status = gBS->AllocatePages(AllocateAddress, EfiBootServicesData, Curr->NumberOfPages, &AllocAddr);
|
||||
if (EFI_SUCCESS == Status)
|
||||
{
|
||||
TotalMem += MultU64x64(SIZE_4KB, Curr->NumberOfPages);
|
||||
}
|
||||
}
|
||||
|
||||
Prev = Curr;
|
||||
Curr = Next;
|
||||
}
|
||||
|
||||
Printf("Fixup Windows mmap issue OK (%lu)\n", TotalMem);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
@@ -0,0 +1,135 @@
|
||||
/******************************************************************************
|
||||
* VtoyUtil.c
|
||||
*
|
||||
* Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Uefi.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/PrintLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DevicePathLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||
#include <Library/UefiApplicationEntryPoint.h>
|
||||
#include <Protocol/LoadedImage.h>
|
||||
#include <Guid/FileInfo.h>
|
||||
#include <Guid/FileSystemInfo.h>
|
||||
#include <Protocol/BlockIo.h>
|
||||
#include <Protocol/RamDisk.h>
|
||||
#include <Protocol/SimpleFileSystem.h>
|
||||
#include <VtoyUtil.h>
|
||||
|
||||
BOOLEAN gVtoyDebugPrint = FALSE;
|
||||
STATIC CONST CHAR16 *gCurFeature= NULL;
|
||||
STATIC CHAR16 *gCmdLine = NULL;
|
||||
STATIC grub_env_printf_pf g_env_printf = NULL;
|
||||
|
||||
STATIC VtoyUtilFeature gFeatureList[] =
|
||||
{
|
||||
{ L"fix_windows_mmap", FixWindowsMemhole },
|
||||
};
|
||||
|
||||
VOID EFIAPI VtoyUtilDebug(IN CONST CHAR8 *Format, ...)
|
||||
{
|
||||
VA_LIST Marker;
|
||||
CHAR8 Buffer[512];
|
||||
|
||||
VA_START (Marker, Format);
|
||||
AsciiVSPrint(Buffer, sizeof(Buffer), Format, Marker);
|
||||
VA_END (Marker);
|
||||
|
||||
if (g_env_printf)
|
||||
{
|
||||
g_env_printf("%s", Buffer);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC EFI_STATUS ParseCmdline(IN EFI_HANDLE ImageHandle)
|
||||
{
|
||||
CHAR16 *pPos = NULL;
|
||||
CHAR16 *pCmdLine = NULL;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
ventoy_grub_param *pGrubParam = NULL;
|
||||
EFI_LOADED_IMAGE_PROTOCOL *pImageInfo = NULL;
|
||||
|
||||
Status = gBS->HandleProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&pImageInfo);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
pCmdLine = (CHAR16 *)AllocatePool(pImageInfo->LoadOptionsSize + 4);
|
||||
SetMem(pCmdLine, pImageInfo->LoadOptionsSize + 4, 0);
|
||||
CopyMem(pCmdLine, pImageInfo->LoadOptions, pImageInfo->LoadOptionsSize);
|
||||
|
||||
if (StrStr(pCmdLine, L"debug"))
|
||||
{
|
||||
gVtoyDebugPrint = TRUE;
|
||||
}
|
||||
|
||||
pPos = StrStr(pCmdLine, L"env_param=");
|
||||
if (!pPos)
|
||||
{
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
pGrubParam = (ventoy_grub_param *)StrHexToUintn(pPos + StrLen(L"env_param="));
|
||||
g_env_printf = pGrubParam->grub_env_printf;
|
||||
|
||||
pPos = StrStr(pCmdLine, L"feature=");
|
||||
if (!pPos)
|
||||
{
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
gCurFeature = pPos + StrLen(L"feature=");
|
||||
|
||||
gCmdLine = pCmdLine;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI VtoyUtilEfiMain
|
||||
(
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
UINTN i;
|
||||
UINTN Len;
|
||||
|
||||
ParseCmdline(ImageHandle);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(gFeatureList); i++)
|
||||
{
|
||||
Len = StrLen(gFeatureList[i].Cmd);
|
||||
if (StrnCmp(gFeatureList[i].Cmd, gCurFeature, Len) == 0)
|
||||
{
|
||||
debug("Find main proc <%s>", gFeatureList[i].Cmd);
|
||||
gFeatureList[i].MainProc(ImageHandle, gCurFeature + Len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FreePool(gCmdLine);
|
||||
gCmdLine = NULL;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
@@ -0,0 +1,63 @@
|
||||
/******************************************************************************
|
||||
* VtoyUtil.h
|
||||
*
|
||||
* Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __VTOYUTIL_H__
|
||||
#define __VTOYUTIL_H__
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
typedef EFI_STATUS (*VTOY_UTIL_PROC_PF)(IN EFI_HANDLE ImageHandle, IN CONST CHAR16 *CmdLine);
|
||||
typedef int (*grub_env_set_pf)(const char *name, const char *val);
|
||||
typedef const char * (*grub_env_get_pf)(const char *name);
|
||||
typedef int (*grub_env_printf_pf)(const char *fmt, ...);
|
||||
|
||||
typedef struct ventoy_grub_param_file_replace
|
||||
{
|
||||
UINT32 magic;
|
||||
char old_file_name[4][256];
|
||||
UINT32 old_file_cnt;
|
||||
UINT32 new_file_virtual_id;
|
||||
}ventoy_grub_param_file_replace;
|
||||
|
||||
typedef struct ventoy_grub_param
|
||||
{
|
||||
grub_env_get_pf grub_env_get;
|
||||
grub_env_set_pf grub_env_set;
|
||||
ventoy_grub_param_file_replace file_replace;
|
||||
grub_env_printf_pf grub_env_printf;
|
||||
}ventoy_grub_param;
|
||||
#pragma pack()
|
||||
|
||||
|
||||
typedef struct VtoyUtilFeature
|
||||
{
|
||||
CONST CHAR16 *Cmd;
|
||||
VTOY_UTIL_PROC_PF MainProc;
|
||||
}VtoyUtilFeature;
|
||||
|
||||
extern BOOLEAN gVtoyDebugPrint;
|
||||
VOID EFIAPI VtoyUtilDebug(IN CONST CHAR8 *Format, ...);
|
||||
#define debug(expr, ...) if (gVtoyDebugPrint) VtoyUtilDebug("[VTOY] "expr"\n", ##__VA_ARGS__)
|
||||
#define Printf VtoyUtilDebug
|
||||
|
||||
EFI_STATUS FixWindowsMemhole(IN EFI_HANDLE ImageHandle, IN CONST CHAR16 *CmdLine);
|
||||
|
||||
#endif
|
||||
|
@@ -0,0 +1,80 @@
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = VtoyUtil
|
||||
FILE_GUID = a43466a0-68c6-469d-ba4b-678bbe90bc47
|
||||
MODULE_TYPE = UEFI_APPLICATION
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = VtoyUtilEfiMain
|
||||
|
||||
|
||||
[Sources]
|
||||
VtoyUtil.h
|
||||
VtoyUtil.c
|
||||
Memhole.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
ShellPkg/ShellPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
UefiApplicationEntryPoint
|
||||
UefiLib
|
||||
DebugLib
|
||||
|
||||
[Guids]
|
||||
gShellVariableGuid
|
||||
gEfiVirtualCdGuid
|
||||
gEfiFileInfoGuid
|
||||
|
||||
[Protocols]
|
||||
gEfiLoadedImageProtocolGuid
|
||||
gEfiBlockIoProtocolGuid
|
||||
gEfiDevicePathProtocolGuid
|
||||
gEfiSimpleFileSystemProtocolGuid
|
||||
gEfiRamDiskProtocolGuid
|
||||
gEfiAbsolutePointerProtocolGuid
|
||||
gEfiAcpiTableProtocolGuid
|
||||
gEfiBlockIo2ProtocolGuid
|
||||
gEfiBusSpecificDriverOverrideProtocolGuid
|
||||
gEfiComponentNameProtocolGuid
|
||||
gEfiComponentName2ProtocolGuid
|
||||
gEfiDriverBindingProtocolGuid
|
||||
gEfiDiskIoProtocolGuid
|
||||
gEfiDiskIo2ProtocolGuid
|
||||
gEfiGraphicsOutputProtocolGuid
|
||||
gEfiHiiConfigAccessProtocolGuid
|
||||
gEfiHiiFontProtocolGuid
|
||||
gEfiLoadFileProtocolGuid
|
||||
gEfiLoadFile2ProtocolGuid
|
||||
gEfiLoadedImageProtocolGuid
|
||||
gEfiLoadedImageDevicePathProtocolGuid
|
||||
gEfiPciIoProtocolGuid
|
||||
gEfiSerialIoProtocolGuid
|
||||
gEfiSimpleTextInProtocolGuid
|
||||
gEfiSimpleTextInputExProtocolGuid
|
||||
gEfiSimpleTextOutProtocolGuid
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -204,6 +204,7 @@
|
||||
|
||||
[Components]
|
||||
MdeModulePkg/Application/Ventoy/Ventoy.inf
|
||||
MdeModulePkg/Application/VtoyUtil/VtoyUtil.inf
|
||||
MdeModulePkg/Application/HelloWorld/HelloWorld.inf
|
||||
MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.inf
|
||||
MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf
|
1141
EDK2/efiffs/mod/grub/grub-core/fs/iso9660.c
Normal file
1141
EDK2/efiffs/mod/grub/grub-core/fs/iso9660.c
Normal file
File diff suppressed because it is too large
Load Diff
794
EDK2/efiffs/mod/src/file.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
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
1137
EDK2/efiffs/org/grub/grub-core/fs/iso9660.c
Normal file
File diff suppressed because it is too large
Load Diff
784
EDK2/efiffs/org/src/file.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
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
EfiISO/ISO/EFI/BOOT/BOOTX64.EFI
Normal file
1
EfiISO/ISO/EFI/BOOT/BOOTX64.EFI
Normal file
@@ -0,0 +1 @@
|
||||
1
|
13
EfiISO/mkefiiso.sh
Normal file
13
EfiISO/mkefiiso.sh
Normal file
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
rm -f ventoy_efiboot.img.*
|
||||
|
||||
cd ISO
|
||||
mkisofs -R -D -sysid VENTOY -V VENTOY -P "longpanda admin@ventoy.net" -p 'https://www.ventoy.net' -o ../ventoy_efiboot.img ./
|
||||
cd ..
|
||||
|
||||
xz --check=crc32 ventoy_efiboot.img
|
||||
|
||||
rm -f ../INSTALL/ventoy/ventoy_efiboot.img.xz
|
||||
cp -a ventoy_efiboot.img.xz ../INSTALL/ventoy/
|
||||
|
@@ -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"
|
||||
|
@@ -114,11 +114,12 @@ static int ventoy_iso_open(const char *path, struct fuse_file_info *file)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ventoy_read_iso_sector(uint32_t sector, uint32_t num, void *buf)
|
||||
static int ventoy_read_iso_sector(uint32_t sector, uint32_t num, char *buf)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint32_t leftSec = 0;
|
||||
uint32_t readSec = 0;
|
||||
off_t offset = 0;
|
||||
dmtable_entry *entry = NULL;
|
||||
|
||||
for (i = 0; i < g_disk_entry_num && num > 0; i++)
|
||||
@@ -127,14 +128,15 @@ static int ventoy_read_iso_sector(uint32_t sector, uint32_t num, void *buf)
|
||||
|
||||
if (sector >= entry->isoSector && sector < entry->isoSector + entry->sectorNum)
|
||||
{
|
||||
lseek(g_disk_fd, (entry->diskSector + (sector - entry->isoSector)) * 512, SEEK_SET);
|
||||
offset = (entry->diskSector + (sector - entry->isoSector)) * 512;
|
||||
|
||||
leftSec = entry->sectorNum - (sector - entry->isoSector);
|
||||
readSec = (leftSec > num) ? num : leftSec;
|
||||
|
||||
read(g_disk_fd, buf, readSec * 512);
|
||||
pread(g_disk_fd, buf, readSec * 512, offset);
|
||||
|
||||
sector += readSec;
|
||||
buf += readSec * 512;
|
||||
num -= readSec;
|
||||
}
|
||||
}
|
||||
|
BIN
FUSEISO/vtoy_fuse_iso_32
Normal file
BIN
FUSEISO/vtoy_fuse_iso_32
Normal file
Binary file not shown.
BIN
FUSEISO/vtoy_fuse_iso_64
Normal file
BIN
FUSEISO/vtoy_fuse_iso_64
Normal file
Binary file not shown.
@@ -809,6 +809,16 @@ module = {
|
||||
common = commands/blocklist.c;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = blscfg;
|
||||
common = commands/blscfg.c;
|
||||
common = commands/loadenv.h;
|
||||
enable = powerpc_ieee1275;
|
||||
enable = efi;
|
||||
enable = i386_pc;
|
||||
enable = emu;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = boot;
|
||||
common = commands/boot.c;
|
||||
@@ -986,6 +996,7 @@ module = {
|
||||
module = {
|
||||
name = loadenv;
|
||||
common = commands/loadenv.c;
|
||||
common = commands/loadenv.h;
|
||||
common = lib/envblk.c;
|
||||
};
|
||||
|
||||
@@ -1578,10 +1589,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;
|
||||
};
|
||||
|
1111
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/blscfg.c
Normal file
1111
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/blscfg.c
Normal file
File diff suppressed because it is too large
Load Diff
894
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/legacycfg.c
Normal file
894
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/legacycfg.c
Normal file
@@ -0,0 +1,894 @@
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2000, 2001, 2010 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/types.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/script_sh.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/legacy_parse.h>
|
||||
#include <grub/crypto.h>
|
||||
#include <grub/auth.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/partition.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
/* Helper for legacy_file. */
|
||||
static grub_err_t
|
||||
legacy_file_getline (char **line, int cont __attribute__ ((unused)),
|
||||
void *data __attribute__ ((unused)))
|
||||
{
|
||||
*line = 0;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
legacy_file (const char *filename)
|
||||
{
|
||||
grub_file_t file;
|
||||
char *entryname = NULL, *entrysrc = NULL;
|
||||
grub_menu_t menu;
|
||||
char *suffix = grub_strdup ("");
|
||||
|
||||
if (!suffix)
|
||||
return grub_errno;
|
||||
|
||||
file = grub_file_open (filename, GRUB_FILE_TYPE_CONFIG);
|
||||
if (! file)
|
||||
{
|
||||
grub_free (suffix);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
menu = grub_env_get_menu ();
|
||||
if (! menu)
|
||||
{
|
||||
menu = grub_zalloc (sizeof (*menu));
|
||||
if (! menu)
|
||||
{
|
||||
grub_free (suffix);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
grub_env_set_menu (menu);
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
char *buf = grub_file_getline (file);
|
||||
char *parsed = NULL;
|
||||
|
||||
if (!buf && grub_errno)
|
||||
{
|
||||
grub_file_close (file);
|
||||
grub_free (suffix);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
if (!buf)
|
||||
break;
|
||||
|
||||
{
|
||||
char *oldname = NULL;
|
||||
char *newsuffix;
|
||||
char *ptr;
|
||||
|
||||
for (ptr = buf; *ptr && grub_isspace (*ptr); ptr++);
|
||||
|
||||
oldname = entryname;
|
||||
parsed = grub_legacy_parse (ptr, &entryname, &newsuffix);
|
||||
grub_free (buf);
|
||||
buf = NULL;
|
||||
if (newsuffix)
|
||||
{
|
||||
char *t;
|
||||
|
||||
t = suffix;
|
||||
suffix = grub_realloc (suffix, grub_strlen (suffix)
|
||||
+ grub_strlen (newsuffix) + 1);
|
||||
if (!suffix)
|
||||
{
|
||||
grub_free (t);
|
||||
grub_free (entrysrc);
|
||||
grub_free (parsed);
|
||||
grub_free (newsuffix);
|
||||
grub_free (suffix);
|
||||
return grub_errno;
|
||||
}
|
||||
grub_memcpy (suffix + grub_strlen (suffix), newsuffix,
|
||||
grub_strlen (newsuffix) + 1);
|
||||
grub_free (newsuffix);
|
||||
newsuffix = NULL;
|
||||
}
|
||||
if (oldname != entryname && oldname)
|
||||
{
|
||||
const char **args = grub_malloc (sizeof (args[0]));
|
||||
if (!args)
|
||||
{
|
||||
grub_file_close (file);
|
||||
return grub_errno;
|
||||
}
|
||||
args[0] = oldname;
|
||||
grub_normal_add_menu_entry (1, args, NULL, NULL, "legacy",
|
||||
NULL, NULL,
|
||||
entrysrc, 0, NULL, NULL);
|
||||
grub_free (args);
|
||||
entrysrc[0] = 0;
|
||||
grub_free (oldname);
|
||||
}
|
||||
}
|
||||
|
||||
if (parsed && !entryname)
|
||||
{
|
||||
grub_normal_parse_line (parsed, legacy_file_getline, NULL);
|
||||
grub_print_error ();
|
||||
grub_free (parsed);
|
||||
parsed = NULL;
|
||||
}
|
||||
else if (parsed)
|
||||
{
|
||||
if (!entrysrc)
|
||||
entrysrc = parsed;
|
||||
else
|
||||
{
|
||||
char *t;
|
||||
|
||||
t = entrysrc;
|
||||
entrysrc = grub_realloc (entrysrc, grub_strlen (entrysrc)
|
||||
+ grub_strlen (parsed) + 1);
|
||||
if (!entrysrc)
|
||||
{
|
||||
grub_free (t);
|
||||
grub_free (parsed);
|
||||
grub_free (suffix);
|
||||
return grub_errno;
|
||||
}
|
||||
grub_memcpy (entrysrc + grub_strlen (entrysrc), parsed,
|
||||
grub_strlen (parsed) + 1);
|
||||
grub_free (parsed);
|
||||
parsed = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
grub_file_close (file);
|
||||
|
||||
if (entryname)
|
||||
{
|
||||
const char **args = grub_malloc (sizeof (args[0]));
|
||||
if (!args)
|
||||
{
|
||||
grub_file_close (file);
|
||||
grub_free (suffix);
|
||||
grub_free (entrysrc);
|
||||
return grub_errno;
|
||||
}
|
||||
args[0] = entryname;
|
||||
grub_normal_add_menu_entry (1, args, NULL, NULL, NULL,
|
||||
NULL, NULL, entrysrc, 0, NULL,
|
||||
NULL);
|
||||
grub_free (args);
|
||||
}
|
||||
|
||||
grub_normal_parse_line (suffix, legacy_file_getline, NULL);
|
||||
grub_print_error ();
|
||||
grub_free (suffix);
|
||||
grub_free (entrysrc);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_legacy_source (struct grub_command *cmd,
|
||||
int argc, char **args)
|
||||
{
|
||||
int new_env, extractor;
|
||||
grub_err_t ret;
|
||||
|
||||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
||||
|
||||
extractor = (cmd->name[0] == 'e');
|
||||
new_env = (cmd->name[extractor ? (sizeof ("extract_legacy_entries_") - 1)
|
||||
: (sizeof ("legacy_") - 1)] == 'c');
|
||||
|
||||
if (new_env)
|
||||
grub_cls ();
|
||||
|
||||
if (new_env && !extractor)
|
||||
grub_env_context_open ();
|
||||
if (extractor)
|
||||
grub_env_extractor_open (!new_env);
|
||||
|
||||
ret = legacy_file (args[0]);
|
||||
|
||||
if (new_env)
|
||||
{
|
||||
grub_menu_t menu;
|
||||
menu = grub_env_get_menu ();
|
||||
if (menu && menu->size)
|
||||
grub_show_menu (menu, 1, 0);
|
||||
if (!extractor)
|
||||
grub_env_context_close ();
|
||||
}
|
||||
if (extractor)
|
||||
grub_env_extractor_close (!new_env);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static enum
|
||||
{
|
||||
GUESS_IT, LINUX, MULTIBOOT, KFREEBSD, KNETBSD, KOPENBSD
|
||||
} kernel_type;
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
int i;
|
||||
#ifdef TODO
|
||||
int no_mem_option = 0;
|
||||
#endif
|
||||
struct grub_command *cmd;
|
||||
char **cutargs;
|
||||
int cutargc;
|
||||
grub_err_t err = GRUB_ERR_NONE;
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
/* FIXME: really support this. */
|
||||
if (argc >= 1 && grub_strcmp (args[0], "--no-mem-option") == 0)
|
||||
{
|
||||
#ifdef TODO
|
||||
no_mem_option = 1;
|
||||
#endif
|
||||
argc--;
|
||||
args++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* linux16 handles both zImages and bzImages. */
|
||||
if (argc >= 1 && (grub_strcmp (args[0], "--type=linux") == 0
|
||||
|| grub_strcmp (args[0], "--type=biglinux") == 0))
|
||||
{
|
||||
kernel_type = LINUX;
|
||||
argc--;
|
||||
args++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argc >= 1 && grub_strcmp (args[0], "--type=multiboot") == 0)
|
||||
{
|
||||
kernel_type = MULTIBOOT;
|
||||
argc--;
|
||||
args++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argc >= 1 && grub_strcmp (args[0], "--type=freebsd") == 0)
|
||||
{
|
||||
kernel_type = KFREEBSD;
|
||||
argc--;
|
||||
args++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argc >= 1 && grub_strcmp (args[0], "--type=openbsd") == 0)
|
||||
{
|
||||
kernel_type = KOPENBSD;
|
||||
argc--;
|
||||
args++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argc >= 1 && grub_strcmp (args[0], "--type=netbsd") == 0)
|
||||
{
|
||||
kernel_type = KNETBSD;
|
||||
argc--;
|
||||
args++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc < 2)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
||||
|
||||
cutargs = grub_malloc (sizeof (cutargs[0]) * (argc - 1));
|
||||
if (!cutargs)
|
||||
return grub_errno;
|
||||
cutargc = argc - 1;
|
||||
grub_memcpy (cutargs + 1, args + 2, sizeof (cutargs[0]) * (argc - 2));
|
||||
cutargs[0] = args[0];
|
||||
|
||||
do
|
||||
{
|
||||
/* First try Linux. */
|
||||
if (kernel_type == GUESS_IT || kernel_type == LINUX)
|
||||
{
|
||||
#ifdef GRUB_MACHINE_PCBIOS
|
||||
cmd = grub_command_find ("linux16");
|
||||
#else
|
||||
cmd = grub_command_find ("linux");
|
||||
#endif
|
||||
if (cmd)
|
||||
{
|
||||
if (!(cmd->func) (cmd, cutargc, cutargs))
|
||||
{
|
||||
kernel_type = LINUX;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
/* Then multiboot. */
|
||||
if (kernel_type == GUESS_IT || kernel_type == MULTIBOOT)
|
||||
{
|
||||
cmd = grub_command_find ("multiboot");
|
||||
if (cmd)
|
||||
{
|
||||
if (!(cmd->func) (cmd, argc, args))
|
||||
{
|
||||
kernel_type = MULTIBOOT;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
{
|
||||
int bsd_device = -1;
|
||||
int bsd_slice = -1;
|
||||
int bsd_part = -1;
|
||||
{
|
||||
grub_device_t dev;
|
||||
const char *hdbiasstr;
|
||||
int hdbias = 0;
|
||||
hdbiasstr = grub_env_get ("legacy_hdbias");
|
||||
if (hdbiasstr)
|
||||
{
|
||||
hdbias = grub_strtoul (hdbiasstr, 0, 0);
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
dev = grub_device_open (0);
|
||||
if (dev && dev->disk
|
||||
&& dev->disk->dev->id == GRUB_DISK_DEVICE_BIOSDISK_ID
|
||||
&& dev->disk->id >= 0x80 && dev->disk->id <= 0x90)
|
||||
{
|
||||
struct grub_partition *part = dev->disk->partition;
|
||||
bsd_device = dev->disk->id - 0x80 - hdbias;
|
||||
if (part && (grub_strcmp (part->partmap->name, "netbsd") == 0
|
||||
|| grub_strcmp (part->partmap->name, "openbsd") == 0
|
||||
|| grub_strcmp (part->partmap->name, "bsd") == 0))
|
||||
{
|
||||
bsd_part = part->number;
|
||||
part = part->parent;
|
||||
}
|
||||
if (part && grub_strcmp (part->partmap->name, "msdos") == 0)
|
||||
bsd_slice = part->number;
|
||||
}
|
||||
if (dev)
|
||||
grub_device_close (dev);
|
||||
}
|
||||
|
||||
/* k*BSD didn't really work well with grub-legacy. */
|
||||
if (kernel_type == GUESS_IT || kernel_type == KFREEBSD)
|
||||
{
|
||||
char buf[sizeof("adXXXXXXXXXXXXsXXXXXXXXXXXXYYY")];
|
||||
if (bsd_device != -1)
|
||||
{
|
||||
if (bsd_slice != -1 && bsd_part != -1)
|
||||
grub_snprintf(buf, sizeof(buf), "ad%ds%d%c", bsd_device,
|
||||
bsd_slice, 'a' + bsd_part);
|
||||
else if (bsd_slice != -1)
|
||||
grub_snprintf(buf, sizeof(buf), "ad%ds%d", bsd_device,
|
||||
bsd_slice);
|
||||
else
|
||||
grub_snprintf(buf, sizeof(buf), "ad%d", bsd_device);
|
||||
grub_env_set ("kFreeBSD.vfs.root.mountfrom", buf);
|
||||
}
|
||||
else
|
||||
grub_env_unset ("kFreeBSD.vfs.root.mountfrom");
|
||||
cmd = grub_command_find ("kfreebsd");
|
||||
if (cmd)
|
||||
{
|
||||
if (!(cmd->func) (cmd, cutargc, cutargs))
|
||||
{
|
||||
kernel_type = KFREEBSD;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
{
|
||||
char **bsdargs;
|
||||
int bsdargc;
|
||||
char bsddevname[sizeof ("wdXXXXXXXXXXXXY")];
|
||||
int found = 0;
|
||||
|
||||
if (bsd_device == -1)
|
||||
{
|
||||
bsdargs = cutargs;
|
||||
bsdargc = cutargc;
|
||||
}
|
||||
else
|
||||
{
|
||||
char rbuf[3] = "-r";
|
||||
bsdargc = cutargc + 2;
|
||||
bsdargs = grub_malloc (sizeof (bsdargs[0]) * bsdargc);
|
||||
if (!bsdargs)
|
||||
{
|
||||
err = grub_errno;
|
||||
goto out;
|
||||
}
|
||||
grub_memcpy (bsdargs, args, argc * sizeof (bsdargs[0]));
|
||||
bsdargs[argc] = rbuf;
|
||||
bsdargs[argc + 1] = bsddevname;
|
||||
grub_snprintf (bsddevname, sizeof (bsddevname),
|
||||
"wd%d%c", bsd_device,
|
||||
bsd_part != -1 ? bsd_part + 'a' : 'c');
|
||||
}
|
||||
if (kernel_type == GUESS_IT || kernel_type == KNETBSD)
|
||||
{
|
||||
cmd = grub_command_find ("knetbsd");
|
||||
if (cmd)
|
||||
{
|
||||
if (!(cmd->func) (cmd, bsdargc, bsdargs))
|
||||
{
|
||||
kernel_type = KNETBSD;
|
||||
found = 1;
|
||||
goto free_bsdargs;
|
||||
}
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
if (kernel_type == GUESS_IT || kernel_type == KOPENBSD)
|
||||
{
|
||||
cmd = grub_command_find ("kopenbsd");
|
||||
if (cmd)
|
||||
{
|
||||
if (!(cmd->func) (cmd, bsdargc, bsdargs))
|
||||
{
|
||||
kernel_type = KOPENBSD;
|
||||
found = 1;
|
||||
goto free_bsdargs;
|
||||
}
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
free_bsdargs:
|
||||
if (bsdargs != cutargs)
|
||||
grub_free (bsdargs);
|
||||
if (found)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (0);
|
||||
|
||||
err = grub_error (GRUB_ERR_BAD_OS, "couldn't load file %s",
|
||||
args[0]);
|
||||
out:
|
||||
grub_free (cutargs);
|
||||
return err;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_legacy_initrd (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
struct grub_command *cmd;
|
||||
|
||||
if (kernel_type == LINUX)
|
||||
{
|
||||
#ifdef GRUB_MACHINE_PCBIOS
|
||||
cmd = grub_command_find ("initrd16");
|
||||
#else
|
||||
cmd = grub_command_find ("initrd");
|
||||
#endif
|
||||
if (!cmd)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"),
|
||||
#ifdef GRUB_MACHINE_PCBIOS
|
||||
"initrd16"
|
||||
#else
|
||||
"initrd"
|
||||
#endif
|
||||
);
|
||||
|
||||
return cmd->func (cmd, argc ? 1 : 0, args);
|
||||
}
|
||||
if (kernel_type == MULTIBOOT)
|
||||
{
|
||||
cmd = grub_command_find ("module");
|
||||
if (!cmd)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"),
|
||||
"module");
|
||||
|
||||
return cmd->func (cmd, argc, args);
|
||||
}
|
||||
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
N_("you need to load the kernel first"));
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_legacy_initrdnounzip (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
struct grub_command *cmd;
|
||||
|
||||
if (kernel_type == LINUX)
|
||||
{
|
||||
cmd = grub_command_find ("initrd16");
|
||||
if (!cmd)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"),
|
||||
"initrd16");
|
||||
|
||||
return cmd->func (cmd, argc, args);
|
||||
}
|
||||
if (kernel_type == MULTIBOOT)
|
||||
{
|
||||
char **newargs;
|
||||
grub_err_t err;
|
||||
char nounzipbuf[10] = "--nounzip";
|
||||
|
||||
cmd = grub_command_find ("module");
|
||||
if (!cmd)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"),
|
||||
"module");
|
||||
|
||||
newargs = grub_malloc ((argc + 1) * sizeof (newargs[0]));
|
||||
if (!newargs)
|
||||
return grub_errno;
|
||||
grub_memcpy (newargs + 1, args, argc * sizeof (newargs[0]));
|
||||
newargs[0] = nounzipbuf;
|
||||
|
||||
err = cmd->func (cmd, argc + 1, newargs);
|
||||
grub_free (newargs);
|
||||
return err;
|
||||
}
|
||||
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
N_("you need to load the kernel first"));
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
check_password_deny (const char *user __attribute__ ((unused)),
|
||||
const char *entered __attribute__ ((unused)),
|
||||
void *password __attribute__ ((unused)))
|
||||
{
|
||||
return GRUB_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
#define MD5_HASHLEN 16
|
||||
|
||||
struct legacy_md5_password
|
||||
{
|
||||
grub_uint8_t *salt;
|
||||
int saltlen;
|
||||
grub_uint8_t hash[MD5_HASHLEN];
|
||||
};
|
||||
|
||||
static int
|
||||
check_password_md5_real (const char *entered,
|
||||
struct legacy_md5_password *pw)
|
||||
{
|
||||
grub_size_t enteredlen = grub_strlen (entered);
|
||||
unsigned char alt_result[MD5_HASHLEN];
|
||||
unsigned char *digest;
|
||||
grub_uint8_t *ctx;
|
||||
grub_size_t i;
|
||||
int ret;
|
||||
|
||||
ctx = grub_zalloc (GRUB_MD_MD5->contextsize);
|
||||
if (!ctx)
|
||||
return 0;
|
||||
|
||||
GRUB_MD_MD5->init (ctx);
|
||||
GRUB_MD_MD5->write (ctx, entered, enteredlen);
|
||||
GRUB_MD_MD5->write (ctx, pw->salt + 3, pw->saltlen - 3);
|
||||
GRUB_MD_MD5->write (ctx, entered, enteredlen);
|
||||
digest = GRUB_MD_MD5->read (ctx);
|
||||
GRUB_MD_MD5->final (ctx);
|
||||
grub_memcpy (alt_result, digest, MD5_HASHLEN);
|
||||
|
||||
GRUB_MD_MD5->init (ctx);
|
||||
GRUB_MD_MD5->write (ctx, entered, enteredlen);
|
||||
GRUB_MD_MD5->write (ctx, pw->salt, pw->saltlen); /* include the $1$ header */
|
||||
for (i = enteredlen; i > 16; i -= 16)
|
||||
GRUB_MD_MD5->write (ctx, alt_result, 16);
|
||||
GRUB_MD_MD5->write (ctx, alt_result, i);
|
||||
|
||||
for (i = enteredlen; i > 0; i >>= 1)
|
||||
GRUB_MD_MD5->write (ctx, entered + ((i & 1) ? enteredlen : 0), 1);
|
||||
digest = GRUB_MD_MD5->read (ctx);
|
||||
GRUB_MD_MD5->final (ctx);
|
||||
|
||||
for (i = 0; i < 1000; i++)
|
||||
{
|
||||
grub_memcpy (alt_result, digest, 16);
|
||||
|
||||
GRUB_MD_MD5->init (ctx);
|
||||
if ((i & 1) != 0)
|
||||
GRUB_MD_MD5->write (ctx, entered, enteredlen);
|
||||
else
|
||||
GRUB_MD_MD5->write (ctx, alt_result, 16);
|
||||
|
||||
if (i % 3 != 0)
|
||||
GRUB_MD_MD5->write (ctx, pw->salt + 3, pw->saltlen - 3);
|
||||
|
||||
if (i % 7 != 0)
|
||||
GRUB_MD_MD5->write (ctx, entered, enteredlen);
|
||||
|
||||
if ((i & 1) != 0)
|
||||
GRUB_MD_MD5->write (ctx, alt_result, 16);
|
||||
else
|
||||
GRUB_MD_MD5->write (ctx, entered, enteredlen);
|
||||
digest = GRUB_MD_MD5->read (ctx);
|
||||
GRUB_MD_MD5->final (ctx);
|
||||
}
|
||||
|
||||
ret = (grub_crypto_memcmp (digest, pw->hash, MD5_HASHLEN) == 0);
|
||||
grub_free (ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
check_password_md5 (const char *user,
|
||||
const char *entered,
|
||||
void *password)
|
||||
{
|
||||
if (!check_password_md5_real (entered, password))
|
||||
return GRUB_ACCESS_DENIED;
|
||||
|
||||
grub_auth_authenticate (user);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static inline int
|
||||
ib64t (char c)
|
||||
{
|
||||
if (c == '.')
|
||||
return 0;
|
||||
if (c == '/')
|
||||
return 1;
|
||||
if (c >= '0' && c <= '9')
|
||||
return c - '0' + 2;
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
return c - 'A' + 12;
|
||||
if (c >= 'a' && c <= 'z')
|
||||
return c - 'a' + 38;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static struct legacy_md5_password *
|
||||
parse_legacy_md5 (int argc, char **args)
|
||||
{
|
||||
const char *salt, *saltend;
|
||||
struct legacy_md5_password *pw = NULL;
|
||||
int i;
|
||||
const char *p;
|
||||
|
||||
if (grub_memcmp (args[0], "--md5", sizeof ("--md5")) != 0)
|
||||
goto fail;
|
||||
if (argc == 1)
|
||||
goto fail;
|
||||
if (grub_strlen(args[1]) <= 3)
|
||||
goto fail;
|
||||
salt = args[1];
|
||||
saltend = grub_strchr (salt + 3, '$');
|
||||
if (!saltend)
|
||||
goto fail;
|
||||
pw = grub_malloc (sizeof (*pw));
|
||||
if (!pw)
|
||||
goto fail;
|
||||
|
||||
p = saltend + 1;
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
int n;
|
||||
grub_uint32_t w = 0;
|
||||
|
||||
for (n = 0; n < 4; n++)
|
||||
{
|
||||
int ww = ib64t(*p++);
|
||||
if (ww == -1)
|
||||
goto fail;
|
||||
w |= ww << (n * 6);
|
||||
}
|
||||
pw->hash[i == 4 ? 5 : 12+i] = w & 0xff;
|
||||
pw->hash[6+i] = (w >> 8) & 0xff;
|
||||
pw->hash[i] = (w >> 16) & 0xff;
|
||||
}
|
||||
{
|
||||
int n;
|
||||
grub_uint32_t w = 0;
|
||||
for (n = 0; n < 2; n++)
|
||||
{
|
||||
int ww = ib64t(*p++);
|
||||
if (ww == -1)
|
||||
goto fail;
|
||||
w |= ww << (6 * n);
|
||||
}
|
||||
if (w >= 0x100)
|
||||
goto fail;
|
||||
pw->hash[11] = w;
|
||||
}
|
||||
|
||||
pw->saltlen = saltend - salt;
|
||||
pw->salt = (grub_uint8_t *) grub_strndup (salt, pw->saltlen);
|
||||
if (!pw->salt)
|
||||
goto fail;
|
||||
|
||||
return pw;
|
||||
|
||||
fail:
|
||||
grub_free (pw);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_legacy_password (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
struct legacy_md5_password *pw = NULL;
|
||||
|
||||
if (argc == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
|
||||
if (args[0][0] != '-' || args[0][1] != '-')
|
||||
return grub_normal_set_password ("legacy", args[0]);
|
||||
|
||||
pw = parse_legacy_md5 (argc, args);
|
||||
|
||||
if (pw)
|
||||
return grub_auth_register_authentication ("legacy", check_password_md5, pw);
|
||||
else
|
||||
/* This is to imitate minor difference between grub-legacy in GRUB2.
|
||||
If 2 password commands are executed in a row and second one fails
|
||||
on GRUB2 the password of first one is used, whereas in grub-legacy
|
||||
authenthication is denied. In case of no password command was executed
|
||||
early both versions deny any access. */
|
||||
return grub_auth_register_authentication ("legacy", check_password_deny,
|
||||
NULL);
|
||||
}
|
||||
|
||||
int
|
||||
grub_legacy_check_md5_password (int argc, char **args,
|
||||
char *entered)
|
||||
{
|
||||
struct legacy_md5_password *pw = NULL;
|
||||
int ret;
|
||||
|
||||
if (args[0][0] != '-' || args[0][1] != '-')
|
||||
{
|
||||
char correct[GRUB_AUTH_MAX_PASSLEN];
|
||||
|
||||
grub_memset (correct, 0, sizeof (correct));
|
||||
grub_strncpy (correct, args[0], sizeof (correct));
|
||||
|
||||
return grub_crypto_memcmp (entered, correct, GRUB_AUTH_MAX_PASSLEN) == 0;
|
||||
}
|
||||
|
||||
pw = parse_legacy_md5 (argc, args);
|
||||
|
||||
if (!pw)
|
||||
return 0;
|
||||
|
||||
ret = check_password_md5_real (entered, pw);
|
||||
grub_free (pw);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_legacy_check_password (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
char entered[GRUB_AUTH_MAX_PASSLEN];
|
||||
|
||||
if (argc == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
|
||||
grub_puts_ (N_("Enter password: "));
|
||||
if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN))
|
||||
return GRUB_ACCESS_DENIED;
|
||||
|
||||
if (!grub_legacy_check_md5_password (argc, args,
|
||||
entered))
|
||||
return GRUB_ACCESS_DENIED;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_command_t cmd_source, cmd_configfile;
|
||||
static grub_command_t cmd_source_extract, cmd_configfile_extract;
|
||||
static grub_command_t cmd_kernel, cmd_initrd, cmd_initrdnounzip;
|
||||
static grub_command_t cmd_password, cmd_check_password;
|
||||
|
||||
GRUB_MOD_INIT(legacycfg)
|
||||
{
|
||||
cmd_source
|
||||
= grub_register_command ("legacy_source",
|
||||
grub_cmd_legacy_source,
|
||||
N_("FILE"),
|
||||
/* TRANSLATORS: "legacy config" means
|
||||
"config as used by grub-legacy". */
|
||||
N_("Parse legacy config in same context"));
|
||||
cmd_configfile
|
||||
= grub_register_command ("legacy_configfile",
|
||||
grub_cmd_legacy_source,
|
||||
N_("FILE"),
|
||||
N_("Parse legacy config in new context"));
|
||||
cmd_source_extract
|
||||
= grub_register_command ("extract_legacy_entries_source",
|
||||
grub_cmd_legacy_source,
|
||||
N_("FILE"),
|
||||
N_("Parse legacy config in same context taking only menu entries"));
|
||||
cmd_configfile_extract
|
||||
= grub_register_command ("extract_legacy_entries_configfile",
|
||||
grub_cmd_legacy_source,
|
||||
N_("FILE"),
|
||||
N_("Parse legacy config in new context taking only menu entries"));
|
||||
|
||||
cmd_kernel = grub_register_command ("legacy_kernel",
|
||||
grub_cmd_legacy_kernel,
|
||||
N_("[--no-mem-option] [--type=TYPE] FILE [ARG ...]"),
|
||||
N_("Simulate grub-legacy `kernel' command"));
|
||||
|
||||
cmd_initrd = grub_register_command ("legacy_initrd",
|
||||
grub_cmd_legacy_initrd,
|
||||
N_("FILE [ARG ...]"),
|
||||
N_("Simulate grub-legacy `initrd' command"));
|
||||
cmd_initrdnounzip = grub_register_command ("legacy_initrd_nounzip",
|
||||
grub_cmd_legacy_initrdnounzip,
|
||||
N_("FILE [ARG ...]"),
|
||||
N_("Simulate grub-legacy `modulenounzip' command"));
|
||||
|
||||
cmd_password = grub_register_command ("legacy_password",
|
||||
grub_cmd_legacy_password,
|
||||
N_("[--md5] PASSWD [FILE]"),
|
||||
N_("Simulate grub-legacy `password' command"));
|
||||
|
||||
cmd_check_password = grub_register_command ("legacy_check_password",
|
||||
grub_cmd_legacy_check_password,
|
||||
N_("[--md5] PASSWD [FILE]"),
|
||||
N_("Simulate grub-legacy `password' command in menu entry mode"));
|
||||
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(legacycfg)
|
||||
{
|
||||
grub_unregister_command (cmd_source);
|
||||
grub_unregister_command (cmd_configfile);
|
||||
grub_unregister_command (cmd_source_extract);
|
||||
grub_unregister_command (cmd_configfile_extract);
|
||||
|
||||
grub_unregister_command (cmd_kernel);
|
||||
grub_unregister_command (cmd_initrd);
|
||||
grub_unregister_command (cmd_initrdnounzip);
|
||||
|
||||
grub_unregister_command (cmd_password);
|
||||
grub_unregister_command (cmd_check_password);
|
||||
}
|
397
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/loadenv.c
Normal file
397
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/loadenv.c
Normal file
@@ -0,0 +1,397 @@
|
||||
/* loadenv.c - command to load/save environment variable. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008,2009,2010 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/dl.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/partition.h>
|
||||
#include <grub/lib/envblk.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
#include "loadenv.h"
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
/* TRANSLATORS: This option is used to override default filename
|
||||
for loading and storing environment. */
|
||||
{"file", 'f', 0, N_("Specify filename."), 0, ARG_TYPE_PATHNAME},
|
||||
{"skip-sig", 's', 0,
|
||||
N_("Skip signature-checking of the environment file."), 0, ARG_TYPE_NONE},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
/* Opens 'filename' with compression filters disabled. Optionally disables the
|
||||
PUBKEY filter (that insists upon properly signed files) as well. PUBKEY
|
||||
filter is restored before the function returns. */
|
||||
static grub_file_t
|
||||
open_envblk_file (char *filename,
|
||||
enum grub_file_type type)
|
||||
{
|
||||
grub_file_t file;
|
||||
char *buf = 0;
|
||||
|
||||
if (! filename)
|
||||
{
|
||||
const char *prefix;
|
||||
int len;
|
||||
|
||||
prefix = grub_env_get ("prefix");
|
||||
if (! prefix)
|
||||
{
|
||||
grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "prefix");
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = grub_strlen (prefix);
|
||||
buf = grub_malloc (len + 1 + sizeof (GRUB_ENVBLK_DEFCFG));
|
||||
if (! buf)
|
||||
return 0;
|
||||
filename = buf;
|
||||
|
||||
grub_strcpy (filename, prefix);
|
||||
filename[len] = '/';
|
||||
grub_strcpy (filename + len + 1, GRUB_ENVBLK_DEFCFG);
|
||||
}
|
||||
|
||||
file = grub_file_open (filename, type);
|
||||
|
||||
grub_free (buf);
|
||||
return file;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_load_env (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
grub_file_t file;
|
||||
grub_envblk_t envblk;
|
||||
grub_env_whitelist_t whitelist;
|
||||
|
||||
whitelist.len = argc;
|
||||
whitelist.list = args;
|
||||
|
||||
/* state[0] is the -f flag; state[1] is the --skip-sig flag */
|
||||
file = open_envblk_file ((state[0].set) ? state[0].arg : 0,
|
||||
GRUB_FILE_TYPE_LOADENV
|
||||
| (state[1].set
|
||||
? GRUB_FILE_TYPE_SKIP_SIGNATURE : GRUB_FILE_TYPE_NONE));
|
||||
if (! file)
|
||||
return grub_errno;
|
||||
|
||||
envblk = read_envblk_file (file);
|
||||
if (! envblk)
|
||||
goto fail;
|
||||
|
||||
/* argc > 0 indicates caller provided a whitelist of variables to read. */
|
||||
grub_envblk_iterate (envblk, argc > 0 ? &whitelist : 0, set_var);
|
||||
grub_envblk_close (envblk);
|
||||
|
||||
fail:
|
||||
grub_file_close (file);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
/* Print all variables in current context. */
|
||||
static int
|
||||
print_var (const char *name, const char *value,
|
||||
void *hook_data __attribute__ ((unused)))
|
||||
{
|
||||
grub_printf ("%s=%s\n", name, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_list_env (grub_extcmd_context_t ctxt,
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
grub_file_t file;
|
||||
grub_envblk_t envblk;
|
||||
|
||||
file = open_envblk_file ((state[0].set) ? state[0].arg : 0,
|
||||
GRUB_FILE_TYPE_LOADENV
|
||||
| (state[1].set
|
||||
? GRUB_FILE_TYPE_SKIP_SIGNATURE : GRUB_FILE_TYPE_NONE));
|
||||
if (! file)
|
||||
return grub_errno;
|
||||
|
||||
envblk = read_envblk_file (file);
|
||||
if (! envblk)
|
||||
goto fail;
|
||||
|
||||
grub_envblk_iterate (envblk, NULL, print_var);
|
||||
grub_envblk_close (envblk);
|
||||
|
||||
fail:
|
||||
grub_file_close (file);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
/* Used to maintain a variable length of blocklists internally. */
|
||||
struct blocklist
|
||||
{
|
||||
grub_disk_addr_t sector;
|
||||
unsigned offset;
|
||||
unsigned length;
|
||||
struct blocklist *next;
|
||||
};
|
||||
|
||||
static void
|
||||
free_blocklists (struct blocklist *p)
|
||||
{
|
||||
struct blocklist *q;
|
||||
|
||||
for (; p; p = q)
|
||||
{
|
||||
q = p->next;
|
||||
grub_free (p);
|
||||
}
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
check_blocklists (grub_envblk_t envblk, struct blocklist *blocklists,
|
||||
grub_file_t file)
|
||||
{
|
||||
grub_size_t total_length;
|
||||
grub_size_t index;
|
||||
grub_disk_t disk;
|
||||
grub_disk_addr_t part_start;
|
||||
struct blocklist *p;
|
||||
char *buf;
|
||||
|
||||
/* Sanity checks. */
|
||||
total_length = 0;
|
||||
for (p = blocklists; p; p = p->next)
|
||||
{
|
||||
struct blocklist *q;
|
||||
/* Check if any pair of blocks overlap. */
|
||||
for (q = p->next; q; q = q->next)
|
||||
{
|
||||
grub_disk_addr_t s1, s2;
|
||||
grub_disk_addr_t e1, e2;
|
||||
|
||||
s1 = p->sector;
|
||||
e1 = s1 + ((p->length + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS);
|
||||
|
||||
s2 = q->sector;
|
||||
e2 = s2 + ((q->length + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS);
|
||||
|
||||
if (s1 < e2 && s2 < e1)
|
||||
{
|
||||
/* This might be actually valid, but it is unbelievable that
|
||||
any filesystem makes such a silly allocation. */
|
||||
return grub_error (GRUB_ERR_BAD_FS, "malformed file");
|
||||
}
|
||||
}
|
||||
|
||||
total_length += p->length;
|
||||
}
|
||||
|
||||
if (total_length != grub_file_size (file))
|
||||
{
|
||||
/* Maybe sparse, unallocated sectors. No way in GRUB. */
|
||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "sparse file not allowed");
|
||||
}
|
||||
|
||||
/* One more sanity check. Re-read all sectors by blocklists, and compare
|
||||
those with the data read via a file. */
|
||||
disk = file->device->disk;
|
||||
|
||||
part_start = grub_partition_get_start (disk->partition);
|
||||
|
||||
buf = grub_envblk_buffer (envblk);
|
||||
char *blockbuf = NULL;
|
||||
grub_size_t blockbuf_len = 0;
|
||||
for (p = blocklists, index = 0; p; index += p->length, p = p->next)
|
||||
{
|
||||
if (p->length > blockbuf_len)
|
||||
{
|
||||
grub_free (blockbuf);
|
||||
blockbuf_len = 2 * p->length;
|
||||
blockbuf = grub_malloc (blockbuf_len);
|
||||
if (!blockbuf)
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
if (grub_disk_read (disk, p->sector - part_start,
|
||||
p->offset, p->length, blockbuf))
|
||||
return grub_errno;
|
||||
|
||||
if (grub_memcmp (buf + index, blockbuf, p->length) != 0)
|
||||
return grub_error (GRUB_ERR_FILE_READ_ERROR, "invalid blocklist");
|
||||
}
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static int
|
||||
write_blocklists (grub_envblk_t envblk, struct blocklist *blocklists,
|
||||
grub_file_t file)
|
||||
{
|
||||
char *buf;
|
||||
grub_disk_t disk;
|
||||
grub_disk_addr_t part_start;
|
||||
struct blocklist *p;
|
||||
grub_size_t index;
|
||||
|
||||
buf = grub_envblk_buffer (envblk);
|
||||
disk = file->device->disk;
|
||||
part_start = grub_partition_get_start (disk->partition);
|
||||
|
||||
index = 0;
|
||||
for (p = blocklists; p; index += p->length, p = p->next)
|
||||
{
|
||||
if (grub_disk_write (disk, p->sector - part_start,
|
||||
p->offset, p->length, buf + index))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Context for grub_cmd_save_env. */
|
||||
struct grub_cmd_save_env_ctx
|
||||
{
|
||||
struct blocklist *head, *tail;
|
||||
};
|
||||
|
||||
/* Store blocklists in a linked list. */
|
||||
static void
|
||||
save_env_read_hook (grub_disk_addr_t sector, unsigned offset, unsigned length,
|
||||
void *data)
|
||||
{
|
||||
struct grub_cmd_save_env_ctx *ctx = data;
|
||||
struct blocklist *block;
|
||||
|
||||
block = grub_malloc (sizeof (*block));
|
||||
if (! block)
|
||||
return;
|
||||
|
||||
block->sector = sector;
|
||||
block->offset = offset;
|
||||
block->length = length;
|
||||
|
||||
/* Slightly complicated, because the list should be FIFO. */
|
||||
block->next = 0;
|
||||
if (ctx->tail)
|
||||
ctx->tail->next = block;
|
||||
ctx->tail = block;
|
||||
if (! ctx->head)
|
||||
ctx->head = block;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_save_env (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
grub_file_t file;
|
||||
grub_envblk_t envblk;
|
||||
struct grub_cmd_save_env_ctx ctx = {
|
||||
.head = 0,
|
||||
.tail = 0
|
||||
};
|
||||
|
||||
if (! argc)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no variable is specified");
|
||||
|
||||
file = open_envblk_file ((state[0].set) ? state[0].arg : 0,
|
||||
GRUB_FILE_TYPE_SAVEENV
|
||||
| GRUB_FILE_TYPE_SKIP_SIGNATURE);
|
||||
if (! file)
|
||||
return grub_errno;
|
||||
|
||||
if (! file->device->disk)
|
||||
{
|
||||
grub_file_close (file);
|
||||
return grub_error (GRUB_ERR_BAD_DEVICE, "disk device required");
|
||||
}
|
||||
|
||||
file->read_hook = save_env_read_hook;
|
||||
file->read_hook_data = &ctx;
|
||||
envblk = read_envblk_file (file);
|
||||
file->read_hook = 0;
|
||||
if (! envblk)
|
||||
goto fail;
|
||||
|
||||
if (check_blocklists (envblk, ctx.head, file))
|
||||
goto fail;
|
||||
|
||||
while (argc)
|
||||
{
|
||||
const char *value;
|
||||
|
||||
value = grub_env_get (args[0]);
|
||||
if (value)
|
||||
{
|
||||
if (! grub_envblk_set (envblk, args[0], value))
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "environment block too small");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else
|
||||
grub_envblk_delete (envblk, args[0]);
|
||||
|
||||
argc--;
|
||||
args++;
|
||||
}
|
||||
|
||||
write_blocklists (envblk, ctx.head, file);
|
||||
|
||||
fail:
|
||||
if (envblk)
|
||||
grub_envblk_close (envblk);
|
||||
free_blocklists (ctx.head);
|
||||
grub_file_close (file);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd_load, cmd_list, cmd_save;
|
||||
|
||||
GRUB_MOD_INIT(loadenv)
|
||||
{
|
||||
cmd_load =
|
||||
grub_register_extcmd ("load_env", grub_cmd_load_env, 0,
|
||||
N_("[-f FILE] [-s|--skip-sig] [variable_name_to_whitelist] [...]"),
|
||||
N_("Load variables from environment block file."),
|
||||
options);
|
||||
cmd_list =
|
||||
grub_register_extcmd ("list_env", grub_cmd_list_env, 0, N_("[-f FILE]"),
|
||||
N_("List variables from environment block file."),
|
||||
options);
|
||||
cmd_save =
|
||||
grub_register_extcmd ("save_env", grub_cmd_save_env, 0,
|
||||
N_("[-f FILE] variable_name [...]"),
|
||||
N_("Save variables to environment block file."),
|
||||
options);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(loadenv)
|
||||
{
|
||||
grub_unregister_extcmd (cmd_load);
|
||||
grub_unregister_extcmd (cmd_list);
|
||||
grub_unregister_extcmd (cmd_save);
|
||||
}
|
93
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/loadenv.h
Normal file
93
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/loadenv.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/* loadenv.c - command to load/save environment variable. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008,2009,2010 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
static grub_envblk_t UNUSED
|
||||
read_envblk_file (grub_file_t file)
|
||||
{
|
||||
grub_off_t offset = 0;
|
||||
char *buf;
|
||||
grub_size_t size = grub_file_size (file);
|
||||
grub_envblk_t envblk;
|
||||
|
||||
buf = grub_malloc (size);
|
||||
if (! buf)
|
||||
return 0;
|
||||
|
||||
while (size > 0)
|
||||
{
|
||||
grub_ssize_t ret;
|
||||
|
||||
ret = grub_file_read (file, buf + offset, size);
|
||||
if (ret <= 0)
|
||||
{
|
||||
grub_free (buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size -= ret;
|
||||
offset += ret;
|
||||
}
|
||||
|
||||
envblk = grub_envblk_open (buf, offset);
|
||||
if (! envblk)
|
||||
{
|
||||
grub_free (buf);
|
||||
grub_error (GRUB_ERR_BAD_FILE_TYPE, "invalid environment block");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return envblk;
|
||||
}
|
||||
|
||||
struct grub_env_whitelist
|
||||
{
|
||||
grub_size_t len;
|
||||
char **list;
|
||||
};
|
||||
typedef struct grub_env_whitelist grub_env_whitelist_t;
|
||||
|
||||
static int UNUSED
|
||||
test_whitelist_membership (const char* name,
|
||||
const grub_env_whitelist_t* whitelist)
|
||||
{
|
||||
grub_size_t i;
|
||||
|
||||
for (i = 0; i < whitelist->len; i++)
|
||||
if (grub_strcmp (name, whitelist->list[i]) == 0)
|
||||
return 1; /* found it */
|
||||
|
||||
return 0; /* not found */
|
||||
}
|
||||
|
||||
/* Helper for grub_cmd_load_env. */
|
||||
static int UNUSED
|
||||
set_var (const char *name, const char *value, void *whitelist)
|
||||
{
|
||||
if (! whitelist)
|
||||
{
|
||||
grub_env_set (name, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (test_whitelist_membership (name,
|
||||
(const grub_env_whitelist_t *) whitelist))
|
||||
grub_env_set (name, value);
|
||||
|
||||
return 0;
|
||||
}
|
349
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/menuentry.c
Normal file
349
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/menuentry.c
Normal file
@@ -0,0 +1,349 @@
|
||||
/* menuentry.c - menuentry command */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/types.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/normal.h>
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{"class", 1, GRUB_ARG_OPTION_REPEATABLE,
|
||||
N_("Menu entry type."), N_("STRING"), ARG_TYPE_STRING},
|
||||
{"users", 2, 0,
|
||||
N_("List of users allowed to boot this entry."), N_("USERNAME[,USERNAME]"),
|
||||
ARG_TYPE_STRING},
|
||||
{"hotkey", 3, 0,
|
||||
N_("Keyboard key to quickly boot this entry."), N_("KEYBOARD_KEY"), ARG_TYPE_STRING},
|
||||
{"source", 4, 0,
|
||||
N_("Use STRING as menu entry body."), N_("STRING"), ARG_TYPE_STRING},
|
||||
{"id", 0, 0, N_("Menu entry identifier."), N_("STRING"), ARG_TYPE_STRING},
|
||||
/* TRANSLATORS: menu entry can either be bootable by anyone or only by
|
||||
handful of users. By default when security is active only superusers can
|
||||
boot a given menu entry. With --unrestricted (this option)
|
||||
anyone can boot it. */
|
||||
{"unrestricted", 0, 0, N_("This entry can be booted by any user."),
|
||||
0, ARG_TYPE_NONE},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static struct
|
||||
{
|
||||
const char *name;
|
||||
int key;
|
||||
} hotkey_aliases[] =
|
||||
{
|
||||
{"backspace", GRUB_TERM_BACKSPACE},
|
||||
{"tab", GRUB_TERM_TAB},
|
||||
{"delete", GRUB_TERM_KEY_DC},
|
||||
{"insert", GRUB_TERM_KEY_INSERT},
|
||||
{"f1", GRUB_TERM_KEY_F1},
|
||||
{"f2", GRUB_TERM_KEY_F2},
|
||||
{"f3", GRUB_TERM_KEY_F3},
|
||||
{"f4", GRUB_TERM_KEY_F4},
|
||||
{"f5", GRUB_TERM_KEY_F5},
|
||||
{"f6", GRUB_TERM_KEY_F6},
|
||||
{"f7", GRUB_TERM_KEY_F7},
|
||||
{"f8", GRUB_TERM_KEY_F8},
|
||||
{"f9", GRUB_TERM_KEY_F9},
|
||||
{"f10", GRUB_TERM_KEY_F10},
|
||||
{"f11", GRUB_TERM_KEY_F11},
|
||||
{"f12", GRUB_TERM_KEY_F12},
|
||||
};
|
||||
|
||||
/* Add a menu entry to the current menu context (as given by the environment
|
||||
variable data slot `menu'). As the configuration file is read, the script
|
||||
parser calls this when a menu entry is to be created. */
|
||||
grub_err_t
|
||||
grub_normal_add_menu_entry (int argc, const char **args,
|
||||
char **classes, const char *id,
|
||||
const char *users, const char *hotkey,
|
||||
const char *prefix, const char *sourcecode,
|
||||
int submenu, int *index, struct bls_entry *bls)
|
||||
{
|
||||
int menu_hotkey = 0;
|
||||
char **menu_args = NULL;
|
||||
char *menu_users = NULL;
|
||||
char *menu_title = NULL;
|
||||
char *menu_sourcecode = NULL;
|
||||
char *menu_id = NULL;
|
||||
struct grub_menu_entry_class *menu_classes = NULL;
|
||||
|
||||
grub_menu_t menu;
|
||||
grub_menu_entry_t *last;
|
||||
|
||||
menu = grub_env_get_menu ();
|
||||
if (! menu)
|
||||
return grub_error (GRUB_ERR_MENU, "no menu context");
|
||||
|
||||
last = &menu->entry_list;
|
||||
|
||||
menu_sourcecode = grub_xasprintf ("%s%s", prefix ?: "", sourcecode);
|
||||
if (! menu_sourcecode)
|
||||
return grub_errno;
|
||||
|
||||
if (classes && classes[0])
|
||||
{
|
||||
int i;
|
||||
for (i = 0; classes[i]; i++); /* count # of menuentry classes */
|
||||
menu_classes = grub_zalloc (sizeof (struct grub_menu_entry_class)
|
||||
* (i + 1));
|
||||
if (! menu_classes)
|
||||
goto fail;
|
||||
|
||||
for (i = 0; classes[i]; i++)
|
||||
{
|
||||
menu_classes[i].name = grub_strdup (classes[i]);
|
||||
if (! menu_classes[i].name)
|
||||
goto fail;
|
||||
menu_classes[i].next = classes[i + 1] ? &menu_classes[i + 1] : NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (users)
|
||||
{
|
||||
menu_users = grub_strdup (users);
|
||||
if (! menu_users)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (hotkey)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < ARRAY_SIZE (hotkey_aliases); i++)
|
||||
if (grub_strcmp (hotkey, hotkey_aliases[i].name) == 0)
|
||||
{
|
||||
menu_hotkey = hotkey_aliases[i].key;
|
||||
break;
|
||||
}
|
||||
if (i == ARRAY_SIZE (hotkey_aliases))
|
||||
menu_hotkey = hotkey[0];
|
||||
}
|
||||
|
||||
if (! argc)
|
||||
{
|
||||
grub_error (GRUB_ERR_MENU, "menuentry is missing title");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
menu_title = grub_strdup (args[0]);
|
||||
if (! menu_title)
|
||||
goto fail;
|
||||
|
||||
grub_dprintf ("menu", "id:\"%s\"\n", id);
|
||||
grub_dprintf ("menu", "title:\"%s\"\n", menu_title);
|
||||
menu_id = grub_strdup (id ? : menu_title);
|
||||
if (! menu_id)
|
||||
goto fail;
|
||||
grub_dprintf ("menu", "menu_id:\"%s\"\n", menu_id);
|
||||
|
||||
/* Save argc, args to pass as parameters to block arg later. */
|
||||
menu_args = grub_malloc (sizeof (char*) * (argc + 1));
|
||||
if (! menu_args)
|
||||
goto fail;
|
||||
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
menu_args[i] = grub_strdup (args[i]);
|
||||
if (! menu_args[i])
|
||||
goto fail;
|
||||
}
|
||||
menu_args[argc] = NULL;
|
||||
}
|
||||
|
||||
/* Add the menu entry at the end of the list. */
|
||||
int ind=0;
|
||||
while (*last)
|
||||
{
|
||||
ind++;
|
||||
last = &(*last)->next;
|
||||
}
|
||||
|
||||
*last = grub_zalloc (sizeof (**last));
|
||||
if (! *last)
|
||||
goto fail;
|
||||
|
||||
(*last)->title = menu_title;
|
||||
(*last)->id = menu_id;
|
||||
(*last)->hotkey = menu_hotkey;
|
||||
(*last)->classes = menu_classes;
|
||||
if (menu_users)
|
||||
(*last)->restricted = 1;
|
||||
(*last)->users = menu_users;
|
||||
(*last)->argc = argc;
|
||||
(*last)->args = menu_args;
|
||||
(*last)->sourcecode = menu_sourcecode;
|
||||
(*last)->submenu = submenu;
|
||||
(*last)->bls = bls;
|
||||
|
||||
menu->size++;
|
||||
if (index)
|
||||
*index = ind;
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
fail:
|
||||
|
||||
grub_free (menu_sourcecode);
|
||||
{
|
||||
int i;
|
||||
for (i = 0; menu_classes && menu_classes[i].name; i++)
|
||||
grub_free (menu_classes[i].name);
|
||||
grub_free (menu_classes);
|
||||
}
|
||||
|
||||
{
|
||||
int i;
|
||||
for (i = 0; menu_args && menu_args[i]; i++)
|
||||
grub_free (menu_args[i]);
|
||||
grub_free (menu_args);
|
||||
}
|
||||
|
||||
grub_free (menu_users);
|
||||
grub_free (menu_title);
|
||||
grub_free (menu_id);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static char *
|
||||
setparams_prefix (int argc, char **args)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
char *p;
|
||||
char *result;
|
||||
grub_size_t len = 10;
|
||||
|
||||
/* Count resulting string length */
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
len += 3; /* 3 = 1 space + 2 quotes */
|
||||
p = args[i];
|
||||
while (*p)
|
||||
len += (*p++ == '\'' ? 3 : 1);
|
||||
}
|
||||
|
||||
result = grub_malloc (len + 2);
|
||||
if (! result)
|
||||
return 0;
|
||||
|
||||
grub_strcpy (result, "setparams");
|
||||
p = result + 9;
|
||||
|
||||
for (j = 0; j < argc; j++)
|
||||
{
|
||||
*p++ = ' ';
|
||||
*p++ = '\'';
|
||||
p = grub_strchrsub (p, args[j], '\'', "'\\''");
|
||||
*p++ = '\'';
|
||||
}
|
||||
*p++ = '\n';
|
||||
*p = '\0';
|
||||
return result;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
char ch;
|
||||
char *src;
|
||||
char *prefix;
|
||||
unsigned len;
|
||||
grub_err_t r;
|
||||
const char *users;
|
||||
|
||||
if (! argc)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing arguments");
|
||||
|
||||
if (ctxt->state[3].set && ctxt->script)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "multiple menuentry definitions");
|
||||
|
||||
if (! ctxt->state[3].set && ! ctxt->script)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no menuentry definition");
|
||||
|
||||
if (ctxt->state[1].set)
|
||||
users = ctxt->state[1].arg;
|
||||
else if (ctxt->state[5].set)
|
||||
users = NULL;
|
||||
else
|
||||
users = "";
|
||||
|
||||
if (! ctxt->script)
|
||||
return grub_normal_add_menu_entry (argc, (const char **) args,
|
||||
(ctxt->state[0].set ? ctxt->state[0].args
|
||||
: NULL),
|
||||
ctxt->state[4].arg,
|
||||
users,
|
||||
ctxt->state[2].arg, 0,
|
||||
ctxt->state[3].arg,
|
||||
ctxt->extcmd->cmd->name[0] == 's',
|
||||
NULL, NULL);
|
||||
|
||||
src = args[argc - 1];
|
||||
args[argc - 1] = NULL;
|
||||
|
||||
len = grub_strlen(src);
|
||||
ch = src[len - 1];
|
||||
src[len - 1] = '\0';
|
||||
|
||||
prefix = setparams_prefix (argc - 1, args);
|
||||
if (! prefix)
|
||||
return grub_errno;
|
||||
|
||||
r = grub_normal_add_menu_entry (argc - 1, (const char **) args,
|
||||
ctxt->state[0].args, ctxt->state[4].arg,
|
||||
users,
|
||||
ctxt->state[2].arg, prefix, src + 1,
|
||||
ctxt->extcmd->cmd->name[0] == 's', NULL,
|
||||
NULL);
|
||||
|
||||
src[len - 1] = ch;
|
||||
args[argc - 1] = src;
|
||||
grub_free (prefix);
|
||||
return r;
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd, cmd_sub;
|
||||
|
||||
void
|
||||
grub_menu_init (void)
|
||||
{
|
||||
cmd = grub_register_extcmd ("menuentry", grub_cmd_menuentry,
|
||||
GRUB_COMMAND_FLAG_BLOCKS
|
||||
| GRUB_COMMAND_ACCEPT_DASH
|
||||
| GRUB_COMMAND_FLAG_EXTRACTOR,
|
||||
N_("BLOCK"), N_("Define a menu entry."), options);
|
||||
cmd_sub = grub_register_extcmd ("submenu", grub_cmd_menuentry,
|
||||
GRUB_COMMAND_FLAG_BLOCKS
|
||||
| GRUB_COMMAND_ACCEPT_DASH
|
||||
| GRUB_COMMAND_FLAG_EXTRACTOR,
|
||||
N_("BLOCK"), N_("Define a submenu."),
|
||||
options);
|
||||
}
|
||||
|
||||
void
|
||||
grub_menu_fini (void)
|
||||
{
|
||||
grub_unregister_extcmd (cmd);
|
||||
grub_unregister_extcmd (cmd_sub);
|
||||
}
|
491
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/test.c
Normal file
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
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
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
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)
|
||||
{
|
@@ -109,6 +109,52 @@ grub_env_write_root (struct grub_env_var *var __attribute__ ((unused)),
|
||||
return grub_strdup (val);
|
||||
}
|
||||
|
||||
static int g_ventoy_hook_root = 0;
|
||||
void ventoy_env_hook_root(int hook)
|
||||
{
|
||||
g_ventoy_hook_root = hook;
|
||||
}
|
||||
|
||||
static char *
|
||||
ventoy_env_write_root (struct grub_env_var *var __attribute__ ((unused)),
|
||||
const char *val)
|
||||
{
|
||||
const char *pos = val;
|
||||
char buf[256];
|
||||
|
||||
if (g_ventoy_hook_root == 0)
|
||||
{
|
||||
return grub_env_write_root(var, val);
|
||||
}
|
||||
|
||||
if (pos[0] == '(')
|
||||
{
|
||||
pos++;
|
||||
}
|
||||
|
||||
if (grub_strncmp(pos, "vtimghd", 7) == 0)
|
||||
{
|
||||
return grub_env_write_root(var, val);
|
||||
}
|
||||
|
||||
pos = grub_strchr(val, ',');
|
||||
if (!pos)
|
||||
{
|
||||
return grub_env_write_root(var, val);
|
||||
}
|
||||
|
||||
if (val[0] == '(')
|
||||
{
|
||||
grub_snprintf(buf, sizeof(buf), "(vtimghd%s", pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_snprintf(buf, sizeof(buf), "vtimghd%s", pos);
|
||||
}
|
||||
|
||||
return grub_env_write_root(var, buf);
|
||||
}
|
||||
|
||||
static void
|
||||
grub_set_prefix_and_root (void)
|
||||
{
|
||||
@@ -123,7 +169,7 @@ grub_set_prefix_and_root (void)
|
||||
if (header->type == OBJ_TYPE_PREFIX)
|
||||
prefix = (char *) header + sizeof (struct grub_module_header);
|
||||
|
||||
grub_register_variable_hook ("root", 0, grub_env_write_root);
|
||||
grub_register_variable_hook ("root", 0, ventoy_env_write_root);
|
||||
|
||||
grub_machine_get_bootlocation (&fwdevice, &fwpath);
|
||||
|
||||
@@ -260,6 +306,45 @@ reclaim_module_space (void)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef GRUB_MACHINE_EFI
|
||||
static int ventoy_legacy_limit_workaround(void)
|
||||
{
|
||||
grub_file_t file;
|
||||
char *pos, *root;
|
||||
char buf[128];
|
||||
|
||||
root = grub_strdup(grub_env_get("root"));
|
||||
if (!root)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
pos = grub_strchr(root, ',');
|
||||
if (pos) *pos = 0;
|
||||
|
||||
grub_snprintf(buf, sizeof(buf), "(%s,1)/ventoy/ventoy.disk.img.xz", root);
|
||||
file = grub_file_open(buf, GRUB_FILE_TYPE_NONE);
|
||||
if (file)
|
||||
{
|
||||
pos = grub_malloc(file->size);
|
||||
if (pos)
|
||||
{
|
||||
grub_file_read(file, pos, file->size);
|
||||
grub_snprintf(buf, sizeof(buf), "loopback ventoydisk mem:0x%lx:size:%lu",
|
||||
(unsigned long)pos, (unsigned long)file->size);
|
||||
|
||||
grub_parser_execute(buf);
|
||||
grub_env_set("prefix", "(ventoydisk)/grub");
|
||||
}
|
||||
|
||||
grub_file_close(file);
|
||||
}
|
||||
|
||||
grub_free(root);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* The main routine. */
|
||||
void __attribute__ ((noreturn))
|
||||
grub_main (void)
|
||||
@@ -293,6 +378,12 @@ grub_main (void)
|
||||
grub_env_export ("root");
|
||||
grub_env_export ("prefix");
|
||||
|
||||
#ifndef GRUB_MACHINE_EFI
|
||||
if (0 == ventoy_check_file_exist("%s/grub.cfg", grub_env_get("prefix"))) {
|
||||
ventoy_legacy_limit_workaround();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Reclaim space used for modules. */
|
||||
reclaim_module_space ();
|
||||
|
1559
GRUB2/MOD_SRC/grub-2.04/grub-core/lib/syslinux_parse.c
Normal file
1559
GRUB2/MOD_SRC/grub-2.04/grub-core/lib/syslinux_parse.c
Normal file
File diff suppressed because it is too large
Load Diff
1585
GRUB2/MOD_SRC/grub-2.04/grub-core/loader/i386/linux.c
Normal file
1585
GRUB2/MOD_SRC/grub-2.04/grub-core/loader/i386/linux.c
Normal file
File diff suppressed because it is too large
Load Diff
214
GRUB2/MOD_SRC/grub-2.04/grub-core/normal/context.c
Normal file
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);
|
||||
}
|
575
GRUB2/MOD_SRC/grub-2.04/grub-core/normal/main.c
Normal file
575
GRUB2/MOD_SRC/grub-2.04/grub-core/normal/main.c
Normal file
@@ -0,0 +1,575 @@
|
||||
/* main.c - the normal mode main routine */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2000,2001,2002,2003,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/kernel.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/menu.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/parser.h>
|
||||
#include <grub/reader.h>
|
||||
#include <grub/menu_viewer.h>
|
||||
#include <grub/auth.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/charset.h>
|
||||
#include <grub/script_sh.h>
|
||||
#include <grub/bufio.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
#define GRUB_DEFAULT_HISTORY_SIZE 50
|
||||
|
||||
static int nested_level = 0;
|
||||
int grub_normal_exit_level = 0;
|
||||
|
||||
void
|
||||
grub_normal_free_menu (grub_menu_t menu)
|
||||
{
|
||||
grub_menu_entry_t entry = menu->entry_list;
|
||||
|
||||
while (entry)
|
||||
{
|
||||
grub_menu_entry_t next_entry = entry->next;
|
||||
grub_size_t i;
|
||||
|
||||
if (entry->classes)
|
||||
{
|
||||
struct grub_menu_entry_class *class;
|
||||
for (class = entry->classes; class; class = class->next)
|
||||
grub_free (class->name);
|
||||
grub_free (entry->classes);
|
||||
}
|
||||
|
||||
if (entry->args)
|
||||
{
|
||||
for (i = 0; entry->args[i]; i++)
|
||||
grub_free (entry->args[i]);
|
||||
grub_free (entry->args);
|
||||
}
|
||||
|
||||
if (entry->bls)
|
||||
{
|
||||
entry->bls->visible = 0;
|
||||
}
|
||||
|
||||
grub_free ((void *) entry->id);
|
||||
grub_free ((void *) entry->users);
|
||||
grub_free ((void *) entry->title);
|
||||
grub_free ((void *) entry->sourcecode);
|
||||
grub_free (entry);
|
||||
entry = next_entry;
|
||||
}
|
||||
|
||||
grub_free (menu);
|
||||
grub_env_unset_menu ();
|
||||
}
|
||||
|
||||
/* Helper for read_config_file. */
|
||||
static grub_err_t
|
||||
read_config_file_getline (char **line, int cont __attribute__ ((unused)),
|
||||
void *data)
|
||||
{
|
||||
grub_file_t file = data;
|
||||
|
||||
while (1)
|
||||
{
|
||||
char *buf;
|
||||
|
||||
*line = buf = grub_file_getline (file);
|
||||
if (! buf)
|
||||
return grub_errno;
|
||||
|
||||
if (buf[0] == '#')
|
||||
grub_free (*line);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_menu_t
|
||||
read_config_file (const char *config)
|
||||
{
|
||||
grub_file_t rawfile, file;
|
||||
char *old_file = 0, *old_dir = 0;
|
||||
char *config_dir, *ptr = 0;
|
||||
const char *ctmp;
|
||||
|
||||
grub_menu_t newmenu;
|
||||
|
||||
newmenu = grub_env_get_menu ();
|
||||
if (! newmenu)
|
||||
{
|
||||
newmenu = grub_zalloc (sizeof (*newmenu));
|
||||
if (! newmenu)
|
||||
return 0;
|
||||
|
||||
grub_env_set_menu (newmenu);
|
||||
}
|
||||
|
||||
/* Try to open the config file. */
|
||||
rawfile = grub_file_open (config, GRUB_FILE_TYPE_CONFIG);
|
||||
if (! rawfile)
|
||||
return 0;
|
||||
|
||||
file = grub_bufio_open (rawfile, 0);
|
||||
if (! file)
|
||||
{
|
||||
grub_file_close (rawfile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctmp = grub_env_get ("config_file");
|
||||
if (ctmp)
|
||||
old_file = grub_strdup (ctmp);
|
||||
ctmp = grub_env_get ("config_directory");
|
||||
if (ctmp)
|
||||
old_dir = grub_strdup (ctmp);
|
||||
if (*config == '(')
|
||||
{
|
||||
grub_env_set ("config_file", config);
|
||||
config_dir = grub_strdup (config);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* $root is guranteed to be defined, otherwise open above would fail */
|
||||
config_dir = grub_xasprintf ("(%s)%s", grub_env_get ("root"), config);
|
||||
if (config_dir)
|
||||
grub_env_set ("config_file", config_dir);
|
||||
}
|
||||
if (config_dir)
|
||||
{
|
||||
ptr = grub_strrchr (config_dir, '/');
|
||||
if (ptr)
|
||||
*ptr = 0;
|
||||
grub_env_set ("config_directory", config_dir);
|
||||
grub_free (config_dir);
|
||||
}
|
||||
|
||||
grub_env_export ("config_file");
|
||||
grub_env_export ("config_directory");
|
||||
|
||||
while (1)
|
||||
{
|
||||
char *line;
|
||||
|
||||
/* Print an error, if any. */
|
||||
grub_print_error ();
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
|
||||
if ((read_config_file_getline (&line, 0, file)) || (! line))
|
||||
break;
|
||||
|
||||
grub_normal_parse_line (line, read_config_file_getline, file);
|
||||
grub_free (line);
|
||||
}
|
||||
|
||||
if (old_file)
|
||||
grub_env_set ("config_file", old_file);
|
||||
else
|
||||
grub_env_unset ("config_file");
|
||||
if (old_dir)
|
||||
grub_env_set ("config_directory", old_dir);
|
||||
else
|
||||
grub_env_unset ("config_directory");
|
||||
grub_free (old_file);
|
||||
grub_free (old_dir);
|
||||
|
||||
grub_file_close (file);
|
||||
|
||||
return newmenu;
|
||||
}
|
||||
|
||||
/* Initialize the screen. */
|
||||
void
|
||||
grub_normal_init_page (struct grub_term_output *term,
|
||||
int y)
|
||||
{
|
||||
grub_ssize_t msg_len;
|
||||
int posx;
|
||||
char *msg_formatted;
|
||||
grub_uint32_t *unicode_msg;
|
||||
grub_uint32_t *last_position;
|
||||
|
||||
grub_term_cls (term);
|
||||
|
||||
msg_formatted = grub_xasprintf (_("GNU GRUB version %s"), PACKAGE_VERSION);
|
||||
if (!msg_formatted)
|
||||
return;
|
||||
|
||||
msg_len = grub_utf8_to_ucs4_alloc (msg_formatted,
|
||||
&unicode_msg, &last_position);
|
||||
grub_free (msg_formatted);
|
||||
|
||||
if (msg_len < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
posx = grub_getstringwidth (unicode_msg, last_position, term);
|
||||
posx = ((int) grub_term_width (term) - posx) / 2;
|
||||
if (posx < 0)
|
||||
posx = 0;
|
||||
grub_term_gotoxy (term, (struct grub_term_coordinate) { posx, y });
|
||||
|
||||
grub_print_ucs4 (unicode_msg, last_position, 0, 0, term);
|
||||
grub_putcode ('\n', term);
|
||||
grub_putcode ('\n', term);
|
||||
grub_free (unicode_msg);
|
||||
}
|
||||
|
||||
static void
|
||||
read_lists (const char *val)
|
||||
{
|
||||
if (! grub_no_modules)
|
||||
{
|
||||
read_command_list (val);
|
||||
read_fs_list (val);
|
||||
read_crypto_list (val);
|
||||
read_terminal_list (val);
|
||||
}
|
||||
grub_gettext_reread_prefix (val);
|
||||
}
|
||||
|
||||
static char *
|
||||
read_lists_hook (struct grub_env_var *var __attribute__ ((unused)),
|
||||
const char *val)
|
||||
{
|
||||
read_lists (val);
|
||||
return val ? grub_strdup (val) : NULL;
|
||||
}
|
||||
|
||||
/* Read the config file CONFIG and execute the menu interface or
|
||||
the command line interface if BATCH is false. */
|
||||
void
|
||||
grub_normal_execute (const char *config, int nested, int batch)
|
||||
{
|
||||
grub_menu_t menu = 0;
|
||||
const char *prefix;
|
||||
|
||||
if (! nested)
|
||||
{
|
||||
prefix = grub_env_get ("prefix");
|
||||
read_lists (prefix);
|
||||
grub_register_variable_hook ("prefix", NULL, read_lists_hook);
|
||||
}
|
||||
|
||||
grub_boot_time ("Executing config file");
|
||||
|
||||
if (config)
|
||||
{
|
||||
menu = read_config_file (config);
|
||||
|
||||
/* Ignore any error. */
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
grub_boot_time ("Executed config file");
|
||||
|
||||
if (! batch)
|
||||
{
|
||||
if (menu && menu->size)
|
||||
{
|
||||
|
||||
grub_boot_time ("Entering menu");
|
||||
grub_show_menu (menu, nested, 0);
|
||||
if (nested)
|
||||
grub_normal_free_menu (menu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This starts the normal mode. */
|
||||
void
|
||||
grub_enter_normal_mode (const char *config)
|
||||
{
|
||||
grub_boot_time ("Entering normal mode");
|
||||
nested_level++;
|
||||
grub_normal_execute (config, 0, 0);
|
||||
grub_boot_time ("Entering shell");
|
||||
grub_cmdline_run (0, 1);
|
||||
nested_level--;
|
||||
if (grub_normal_exit_level)
|
||||
grub_normal_exit_level--;
|
||||
grub_boot_time ("Exiting normal mode");
|
||||
}
|
||||
|
||||
/* Enter normal mode from rescue mode. */
|
||||
static grub_err_t
|
||||
grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
if (argc == 0)
|
||||
{
|
||||
/* Guess the config filename. It is necessary to make CONFIG static,
|
||||
so that it won't get broken by longjmp. */
|
||||
char *config;
|
||||
const char *prefix;
|
||||
|
||||
prefix = grub_env_get ("prefix");
|
||||
if (prefix)
|
||||
{
|
||||
config = grub_xasprintf ("%s/grub.cfg", prefix);
|
||||
if (! config)
|
||||
goto quit;
|
||||
|
||||
grub_enter_normal_mode (config);
|
||||
grub_free (config);
|
||||
}
|
||||
else
|
||||
grub_enter_normal_mode (0);
|
||||
}
|
||||
else
|
||||
grub_enter_normal_mode (argv[0]);
|
||||
|
||||
quit:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Exit from normal mode to rescue mode. */
|
||||
static grub_err_t
|
||||
grub_cmd_normal_exit (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char *argv[] __attribute__ ((unused)))
|
||||
{
|
||||
if (nested_level <= grub_normal_exit_level)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "not in normal environment");
|
||||
grub_normal_exit_level++;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_normal_reader_init (int nested)
|
||||
{
|
||||
struct grub_term_output *term;
|
||||
const char *msg_esc = _("ESC at any time exits.");
|
||||
char *msg_formatted;
|
||||
|
||||
msg_formatted = grub_xasprintf (_("Minimal BASH-like line editing is supported. For "
|
||||
"the first word, TAB lists possible command completions. Anywhere "
|
||||
"else TAB lists possible device or file completions. %s"),
|
||||
nested ? msg_esc : "");
|
||||
if (!msg_formatted)
|
||||
return grub_errno;
|
||||
|
||||
FOR_ACTIVE_TERM_OUTPUTS(term)
|
||||
{
|
||||
grub_normal_init_page (term, 1);
|
||||
grub_term_setcursor (term, 1);
|
||||
|
||||
if (grub_term_width (term) > 3 + STANDARD_MARGIN + 20)
|
||||
grub_print_message_indented (msg_formatted, 3, STANDARD_MARGIN, term);
|
||||
else
|
||||
grub_print_message_indented (msg_formatted, 0, 0, term);
|
||||
grub_putcode ('\n', term);
|
||||
grub_putcode ('\n', term);
|
||||
grub_putcode ('\n', term);
|
||||
}
|
||||
grub_free (msg_formatted);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_normal_read_line_real (char **line, int cont, int nested)
|
||||
{
|
||||
const char *prompt;
|
||||
|
||||
if (cont)
|
||||
/* TRANSLATORS: it's command line prompt. */
|
||||
prompt = _(">");
|
||||
else
|
||||
/* TRANSLATORS: it's command line prompt. */
|
||||
prompt = _("grub>");
|
||||
|
||||
if (!prompt)
|
||||
return grub_errno;
|
||||
|
||||
while (1)
|
||||
{
|
||||
*line = grub_cmdline_get (prompt);
|
||||
if (*line)
|
||||
return 0;
|
||||
|
||||
if (cont || nested)
|
||||
{
|
||||
grub_free (*line);
|
||||
*line = 0;
|
||||
return grub_errno;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_normal_read_line (char **line, int cont,
|
||||
void *data __attribute__ ((unused)))
|
||||
{
|
||||
return grub_normal_read_line_real (line, cont, 0);
|
||||
}
|
||||
|
||||
void
|
||||
grub_cmdline_run (int nested, int force_auth)
|
||||
{
|
||||
grub_err_t err = GRUB_ERR_NONE;
|
||||
|
||||
do
|
||||
{
|
||||
err = grub_auth_check_authentication (NULL);
|
||||
}
|
||||
while (err && force_auth);
|
||||
|
||||
if (err)
|
||||
{
|
||||
grub_print_error ();
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
grub_normal_reader_init (nested);
|
||||
|
||||
while (1)
|
||||
{
|
||||
char *line = NULL;
|
||||
|
||||
if (grub_normal_exit_level)
|
||||
break;
|
||||
|
||||
/* Print an error, if any. */
|
||||
grub_print_error ();
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
|
||||
grub_normal_read_line_real (&line, 0, nested);
|
||||
if (! line)
|
||||
break;
|
||||
|
||||
grub_normal_parse_line (line, grub_normal_read_line, NULL);
|
||||
grub_free (line);
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
grub_env_write_pager (struct grub_env_var *var __attribute__ ((unused)),
|
||||
const char *val)
|
||||
{
|
||||
grub_set_more ((*val == '1'));
|
||||
return grub_strdup (val);
|
||||
}
|
||||
|
||||
/* clear */
|
||||
static grub_err_t
|
||||
grub_mini_cmd_clear (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char *argv[] __attribute__ ((unused)))
|
||||
{
|
||||
grub_cls ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_command_t cmd_clear;
|
||||
|
||||
static void (*grub_xputs_saved) (const char *str);
|
||||
static const char *features[] = {
|
||||
"feature_chainloader_bpb", "feature_ntldr", "feature_platform_search_hint",
|
||||
"feature_default_font_path", "feature_all_video_module",
|
||||
"feature_menuentry_id", "feature_menuentry_options", "feature_200_final",
|
||||
"feature_nativedisk_cmd", "feature_timeout_style"
|
||||
};
|
||||
|
||||
GRUB_MOD_INIT(normal)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
grub_boot_time ("Preparing normal module");
|
||||
|
||||
/* Previously many modules depended on gzio. Be nice to user and load it. */
|
||||
grub_dl_load ("gzio");
|
||||
grub_errno = 0;
|
||||
|
||||
grub_normal_auth_init ();
|
||||
grub_context_init ();
|
||||
grub_script_init ();
|
||||
grub_menu_init ();
|
||||
|
||||
grub_xputs_saved = grub_xputs;
|
||||
grub_xputs = grub_xputs_normal;
|
||||
|
||||
/* Normal mode shouldn't be unloaded. */
|
||||
if (mod)
|
||||
grub_dl_ref (mod);
|
||||
|
||||
cmd_clear =
|
||||
grub_register_command ("clear", grub_mini_cmd_clear,
|
||||
0, N_("Clear the screen."));
|
||||
|
||||
grub_set_history (GRUB_DEFAULT_HISTORY_SIZE);
|
||||
|
||||
grub_register_variable_hook ("pager", 0, grub_env_write_pager);
|
||||
grub_env_export ("pager");
|
||||
|
||||
/* Register a command "normal" for the rescue mode. */
|
||||
grub_register_command ("normal", grub_cmd_normal,
|
||||
0, N_("Enter normal mode."));
|
||||
grub_register_command ("normal_exit", grub_cmd_normal_exit,
|
||||
0, N_("Exit from normal mode."));
|
||||
|
||||
/* Reload terminal colors when these variables are written to. */
|
||||
grub_register_variable_hook ("color_normal", NULL, grub_env_write_color_normal);
|
||||
grub_register_variable_hook ("color_highlight", NULL, grub_env_write_color_highlight);
|
||||
|
||||
/* Preserve hooks after context changes. */
|
||||
grub_env_export ("color_normal");
|
||||
grub_env_export ("color_highlight");
|
||||
|
||||
/* Set default color names. */
|
||||
grub_env_set ("color_normal", "light-gray/black");
|
||||
grub_env_set ("color_highlight", "black/light-gray");
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE (features); i++)
|
||||
{
|
||||
grub_env_set (features[i], "y");
|
||||
grub_env_export (features[i]);
|
||||
}
|
||||
grub_env_set ("grub_cpu", GRUB_TARGET_CPU);
|
||||
grub_env_export ("grub_cpu");
|
||||
grub_env_set ("grub_platform", GRUB_PLATFORM);
|
||||
grub_env_export ("grub_platform");
|
||||
|
||||
grub_boot_time ("Normal module prepared");
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(normal)
|
||||
{
|
||||
grub_context_fini ();
|
||||
grub_script_fini ();
|
||||
grub_menu_fini ();
|
||||
grub_normal_auth_fini ();
|
||||
|
||||
grub_xputs = grub_xputs_saved;
|
||||
|
||||
grub_set_history (0);
|
||||
grub_register_variable_hook ("pager", 0, 0);
|
||||
grub_fs_autoload_hook = 0;
|
||||
grub_unregister_command (cmd_clear);
|
||||
}
|
@@ -38,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,51 +803,75 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
|
||||
goto refresh;
|
||||
|
||||
case GRUB_TERM_KEY_F2:
|
||||
cmdstr = grub_env_get("VTOY_F2_CMD");
|
||||
if (cmdstr)
|
||||
{
|
||||
menu_fini ();
|
||||
grub_script_execute_sourcecode(cmdstr);
|
||||
goto refresh;
|
||||
case '2':
|
||||
if (0 == g_ventoy_fn_mutex) {
|
||||
cmdstr = grub_env_get("VTOY_F2_CMD");
|
||||
if (cmdstr)
|
||||
{
|
||||
menu_fini ();
|
||||
g_ventoy_fn_mutex = 1;
|
||||
grub_script_execute_sourcecode(cmdstr);
|
||||
g_ventoy_fn_mutex = 0;
|
||||
goto refresh;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GRUB_TERM_KEY_F3:
|
||||
cmdstr = grub_env_get("VTOY_F3_CMD");
|
||||
if (cmdstr)
|
||||
{
|
||||
menu_fini ();
|
||||
grub_script_execute_sourcecode(cmdstr);
|
||||
goto refresh;
|
||||
case '3':
|
||||
if (0 == g_ventoy_fn_mutex) {
|
||||
cmdstr = grub_env_get("VTOY_F3_CMD");
|
||||
if (cmdstr)
|
||||
{
|
||||
menu_fini ();
|
||||
grub_script_execute_sourcecode(cmdstr);
|
||||
goto refresh;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GRUB_TERM_KEY_F4:
|
||||
cmdstr = grub_env_get("VTOY_F4_CMD");
|
||||
if (cmdstr)
|
||||
{
|
||||
menu_fini ();
|
||||
grub_script_execute_sourcecode(cmdstr);
|
||||
goto refresh;
|
||||
case '4':
|
||||
if (0 == g_ventoy_fn_mutex) {
|
||||
cmdstr = grub_env_get("VTOY_F4_CMD");
|
||||
if (cmdstr)
|
||||
{
|
||||
menu_fini ();
|
||||
g_ventoy_fn_mutex = 1;
|
||||
grub_script_execute_sourcecode(cmdstr);
|
||||
g_ventoy_fn_mutex = 0;
|
||||
goto refresh;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GRUB_TERM_KEY_F5:
|
||||
cmdstr = grub_env_get("VTOY_F5_CMD");
|
||||
if (cmdstr)
|
||||
{
|
||||
menu_fini ();
|
||||
grub_script_execute_sourcecode(cmdstr);
|
||||
goto refresh;
|
||||
case '5':
|
||||
if (0 == g_ventoy_fn_mutex) {
|
||||
cmdstr = grub_env_get("VTOY_F5_CMD");
|
||||
if (cmdstr)
|
||||
{
|
||||
menu_fini ();
|
||||
g_ventoy_fn_mutex = 1;
|
||||
grub_script_execute_sourcecode(cmdstr);
|
||||
g_ventoy_fn_mutex = 0;
|
||||
goto refresh;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GRUB_TERM_KEY_F6:
|
||||
cmdstr = grub_env_get("VTOY_F6_CMD");
|
||||
if (cmdstr)
|
||||
{
|
||||
menu_fini ();
|
||||
grub_script_execute_sourcecode(cmdstr);
|
||||
goto refresh;
|
||||
case '6':
|
||||
if (0 == g_ventoy_fn_mutex) {
|
||||
cmdstr = grub_env_get("VTOY_F6_CMD");
|
||||
if (cmdstr)
|
||||
{
|
||||
menu_fini ();
|
||||
g_ventoy_fn_mutex = 1;
|
||||
grub_script_execute_sourcecode(cmdstr);
|
||||
g_ventoy_fn_mutex = 0;
|
||||
goto refresh;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GRUB_TERM_KEY_F7:
|
||||
case '7':
|
||||
cmdstr = grub_env_get("VTOY_F7_CMD");
|
||||
if (cmdstr)
|
||||
{
|
||||
@@ -852,6 +881,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
|
||||
}
|
||||
break;
|
||||
case GRUB_TERM_KEY_F1:
|
||||
case '1':
|
||||
menu_fini ();
|
||||
g_ventoy_memdisk_mode = 1 - g_ventoy_memdisk_mode;
|
||||
g_ventoy_menu_refresh = 1;
|
||||
@@ -950,11 +980,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)
|
607
GRUB2/MOD_SRC/grub-2.04/grub-core/normal/menu_text.c
Normal file
607
GRUB2/MOD_SRC/grub-2.04/grub-core/normal/menu_text.c
Normal file
@@ -0,0 +1,607 @@
|
||||
/* 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)
|
||||
{
|
||||
#if 0
|
||||
ret += grub_print_message_indented_real
|
||||
(_("Press enter to boot the selected OS, "
|
||||
"`e' to edit the commands before booting "
|
||||
"or `c' for a command-line. ESC to return previous menu."),
|
||||
STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
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"),
|
||||
3, 6, 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
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;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -23,7 +23,12 @@
|
||||
|
||||
#define VTOY_MAX_SCRIPT_BUF (4 * 1024 * 1024)
|
||||
|
||||
#define VTOY_SIZE_1GB 1073741824
|
||||
#define VTOY_PART_BUF_LEN (128 * 1024)
|
||||
|
||||
#define VTOY_FILT_MIN_FILE_SIZE 32768
|
||||
|
||||
#define VTOY_SIZE_1GB 1073741824
|
||||
#define VTOY_SIZE_512KB (512 * 1024)
|
||||
|
||||
#define JSON_SUCCESS 0
|
||||
#define JSON_FAILED 1
|
||||
@@ -62,6 +67,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 +93,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 +125,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 +216,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 +237,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 +384,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 +446,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;
|
||||
|
||||
|
||||
@@ -420,14 +469,19 @@ grub_err_t ventoy_cmd_linux_locate_initrd(grub_extcmd_context_t ctxt, int argc,
|
||||
grub_err_t ventoy_cmd_initrd_count(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_valid_initrd_count(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_cpio_busybox_64(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_trailer_cpio(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
int ventoy_cpio_newc_fill_head(void *buf, int filesize, const void *filedata, const char *name);
|
||||
grub_file_t ventoy_grub_file_open(enum grub_file_type type, const char *fmt, ...);
|
||||
grub_uint64_t ventoy_grub_get_file_size(const char *fmt, ...);
|
||||
int ventoy_is_file_exist(const char *fmt, ...);
|
||||
int ventoy_is_dir_exist(const char *fmt, ...);
|
||||
int ventoy_fill_data(grub_uint32_t buflen, char *buffer);
|
||||
grub_err_t ventoy_cmd_load_plugin(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_wimdows_reset(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_wimdows_locate_wim(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_windows_chain_data(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_wim_chain_data(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_dump_wim_patch(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
|
||||
VTOY_JSON *vtoy_json_find_item
|
||||
(
|
||||
@@ -552,26 +606,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)
|
||||
{
|
||||
@@ -565,6 +564,14 @@ grub_err_t ventoy_cmd_specify_initrd_file(grub_extcmd_context_t ctxt, int argc,
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
||||
static int ventoy_cpio_newc_get_int(char *value)
|
||||
{
|
||||
char buf[16] = {0};
|
||||
|
||||
grub_memcpy(buf, value, 8);
|
||||
return (int)grub_strtoul(buf, NULL, 16);
|
||||
}
|
||||
|
||||
static void ventoy_cpio_newc_fill_int(grub_uint32_t value, char *buf, int buflen)
|
||||
{
|
||||
int i;
|
||||
@@ -686,6 +693,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 +708,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 +732,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 +848,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;
|
||||
@@ -850,10 +910,61 @@ grub_err_t ventoy_cmd_linux_locate_initrd(grub_extcmd_context_t ctxt, int argc,
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
||||
static int ventoy_cpio_busybox64(cpio_newc_header *head)
|
||||
{
|
||||
char *name;
|
||||
int namelen;
|
||||
int offset;
|
||||
int count = 0;
|
||||
|
||||
name = (char *)(head + 1);
|
||||
while (name[0] && count < 2)
|
||||
{
|
||||
if (grub_strcmp(name, "ventoy/busybox/ash") == 0)
|
||||
{
|
||||
grub_memcpy(name, "ventoy/busybox/32h", 18);
|
||||
count++;
|
||||
}
|
||||
else if (grub_strcmp(name, "ventoy/busybox/64h") == 0)
|
||||
{
|
||||
grub_memcpy(name, "ventoy/busybox/ash", 18);
|
||||
count++;
|
||||
}
|
||||
|
||||
namelen = ventoy_cpio_newc_get_int(head->c_namesize);
|
||||
offset = sizeof(cpio_newc_header) + namelen;
|
||||
offset = ventoy_align(offset, 4);
|
||||
offset += ventoy_cpio_newc_get_int(head->c_filesize);
|
||||
offset = ventoy_align(offset, 4);
|
||||
|
||||
head = (cpio_newc_header *)((char *)head + offset);
|
||||
name = (char *)(head + 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
grub_err_t ventoy_cmd_cpio_busybox_64(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
(void)ctxt;
|
||||
(void)argc;
|
||||
(void)args;
|
||||
|
||||
debug("ventoy_cmd_busybox_64 %d\n", argc);
|
||||
ventoy_cpio_busybox64((cpio_newc_header *)g_ventoy_cpio_buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
grub_err_t ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
int 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,13 +972,16 @@ 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;
|
||||
|
||||
if (argc != 3)
|
||||
if (argc != 4)
|
||||
{
|
||||
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s cpiofile\n", cmd_raw_name);
|
||||
}
|
||||
@@ -892,30 +1006,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 +1095,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);
|
||||
@@ -964,6 +1134,102 @@ grub_err_t ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **arg
|
||||
|
||||
grub_file_close(file);
|
||||
|
||||
if (grub_strcmp(args[3], "busybox=64") == 0)
|
||||
{
|
||||
debug("cpio busybox proc %s\n", args[3]);
|
||||
ventoy_cpio_busybox64((cpio_newc_header *)g_ventoy_cpio_buf);
|
||||
}
|
||||
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_trailer_cpio(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
int mod;
|
||||
int bufsize;
|
||||
int namelen;
|
||||
int offset;
|
||||
char *name;
|
||||
grub_uint8_t *bufend;
|
||||
cpio_newc_header *head;
|
||||
grub_file_t file;
|
||||
char value[64];
|
||||
const grub_uint8_t trailler[124] = {
|
||||
0x30, 0x37, 0x30, 0x37, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30,
|
||||
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||
0x30, 0x30, 0x30, 0x30, 0x30, 0x42, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x54, 0x52,
|
||||
0x41, 0x49, 0x4C, 0x45, 0x52, 0x21, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
(void)ctxt;
|
||||
(void)argc;
|
||||
|
||||
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", args[0], args[1]);
|
||||
if (!file)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
grub_memset(g_ventoy_runtime_buf, 0, sizeof(ventoy_os_param));
|
||||
ventoy_fill_os_param(file, (ventoy_os_param *)g_ventoy_runtime_buf);
|
||||
|
||||
grub_file_close(file);
|
||||
|
||||
grub_memcpy(g_ventoy_initrd_head, trailler, sizeof(trailler));
|
||||
bufend = (grub_uint8_t *)g_ventoy_initrd_head + sizeof(trailler);
|
||||
|
||||
bufsize = (int)(bufend - g_ventoy_cpio_buf);
|
||||
mod = bufsize % 512;
|
||||
if (mod)
|
||||
{
|
||||
grub_memset(bufend, 0, 512 - mod);
|
||||
bufsize += 512 - mod;
|
||||
}
|
||||
|
||||
if (argc > 1 && grub_strcmp(args[2], "noinit") == 0)
|
||||
{
|
||||
head = (cpio_newc_header *)g_ventoy_cpio_buf;
|
||||
name = (char *)(head + 1);
|
||||
|
||||
while (grub_strcmp(name, "TRAILER!!!"))
|
||||
{
|
||||
if (grub_strcmp(name, "init") == 0)
|
||||
{
|
||||
grub_memcpy(name, "xxxx", 4);
|
||||
}
|
||||
else if (grub_strcmp(name, "linuxrc") == 0)
|
||||
{
|
||||
grub_memcpy(name, "vtoyxrc", 7);
|
||||
}
|
||||
else if (grub_strcmp(name, "sbin") == 0)
|
||||
{
|
||||
grub_memcpy(name, "vtoy", 4);
|
||||
}
|
||||
else if (grub_strcmp(name, "sbin/init") == 0)
|
||||
{
|
||||
grub_memcpy(name, "vtoy/vtoy", 9);
|
||||
}
|
||||
|
||||
namelen = ventoy_cpio_newc_get_int(head->c_namesize);
|
||||
offset = sizeof(cpio_newc_header) + namelen;
|
||||
offset = ventoy_align(offset, 4);
|
||||
offset += ventoy_cpio_newc_get_int(head->c_filesize);
|
||||
offset = ventoy_align(offset, 4);
|
||||
|
||||
head = (cpio_newc_header *)((char *)head + offset);
|
||||
name = (char *)(head + 1);
|
||||
}
|
||||
}
|
||||
|
||||
grub_snprintf(value, sizeof(value), "0x%llx", (ulonglong)(ulong)g_ventoy_cpio_buf);
|
||||
ventoy_set_env("ventoy_cpio_addr", value);
|
||||
grub_snprintf(value, sizeof(value), "%d", bufsize);
|
||||
ventoy_set_env("ventoy_cpio_size", value);
|
||||
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
||||
@@ -1067,6 +1333,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 */
|
1415
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_plugin.c
Normal file
1415
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_plugin.c
Normal file
File diff suppressed because it is too large
Load Diff
631
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_unix.c
Normal file
631
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_unix.c
Normal file
@@ -0,0 +1,631 @@
|
||||
/******************************************************************************
|
||||
* ventoy_unix.c
|
||||
*
|
||||
* Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#include <grub/types.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/device.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/partition.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/datetime.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/net.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/ventoy.h>
|
||||
#include "ventoy_def.h"
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
char g_ko_mod_path[256];
|
||||
int g_conf_new_len = 0;
|
||||
char *g_conf_new_data = NULL;
|
||||
|
||||
int g_mod_new_len = 0;
|
||||
char *g_mod_new_data = NULL;
|
||||
|
||||
grub_uint64_t g_mod_override_offset = 0;
|
||||
grub_uint64_t g_conf_override_offset = 0;
|
||||
|
||||
static int ventoy_get_file_override(const char *filename, grub_uint64_t *offset)
|
||||
{
|
||||
grub_file_t file;
|
||||
|
||||
*offset = 0;
|
||||
|
||||
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "(loop)%s", filename);
|
||||
if (!file)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
*offset = grub_iso9660_get_last_file_dirent_pos(file) + 2;
|
||||
|
||||
grub_file_close(file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_uint32_t ventoy_unix_get_override_chunk_count(void)
|
||||
{
|
||||
grub_uint32_t count = 0;
|
||||
|
||||
if (g_conf_new_len > 0)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
if (g_mod_new_len > 0)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static grub_uint32_t ventoy_unix_get_virt_chunk_count(void)
|
||||
{
|
||||
grub_uint32_t count = 0;
|
||||
|
||||
if (g_conf_new_len > 0)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
if (g_mod_new_len > 0)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
static grub_uint32_t ventoy_unix_get_virt_chunk_size(void)
|
||||
{
|
||||
grub_uint32_t size;
|
||||
|
||||
size = sizeof(ventoy_virt_chunk) * ventoy_unix_get_virt_chunk_count();
|
||||
|
||||
if (g_conf_new_len > 0)
|
||||
{
|
||||
size += ventoy_align_2k(g_conf_new_len);
|
||||
}
|
||||
|
||||
if (g_mod_new_len > 0)
|
||||
{
|
||||
size += ventoy_align_2k(g_mod_new_len);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static void ventoy_unix_fill_override_data( grub_uint64_t isosize, void *override)
|
||||
{
|
||||
grub_uint64_t sector;
|
||||
ventoy_override_chunk *cur;
|
||||
ventoy_iso9660_override *dirent;
|
||||
|
||||
sector = (isosize + 2047) / 2048;
|
||||
|
||||
cur = (ventoy_override_chunk *)override;
|
||||
|
||||
if (g_conf_new_len > 0)
|
||||
{
|
||||
/* loader.conf */
|
||||
cur->img_offset = g_conf_override_offset;
|
||||
cur->override_size = sizeof(ventoy_iso9660_override);
|
||||
dirent = (ventoy_iso9660_override *)cur->override_data;
|
||||
dirent->first_sector = (grub_uint32_t)sector;
|
||||
dirent->size = (grub_uint32_t)g_conf_new_len;
|
||||
dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector);
|
||||
dirent->size_be = grub_swap_bytes32(dirent->size);
|
||||
sector += (dirent->size + 2047) / 2048;
|
||||
}
|
||||
|
||||
if (g_mod_new_len > 0)
|
||||
{
|
||||
/* mod.ko */
|
||||
cur++;
|
||||
cur->img_offset = g_mod_override_offset;
|
||||
cur->override_size = sizeof(ventoy_iso9660_override);
|
||||
dirent = (ventoy_iso9660_override *)cur->override_data;
|
||||
dirent->first_sector = (grub_uint32_t)sector;
|
||||
dirent->size = (grub_uint32_t)g_mod_new_len;
|
||||
dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector);
|
||||
dirent->size_be = grub_swap_bytes32(dirent->size);
|
||||
sector += (dirent->size + 2047) / 2048;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void ventoy_unix_fill_virt_data( grub_uint64_t isosize, ventoy_chain_head *chain)
|
||||
{
|
||||
grub_uint64_t sector;
|
||||
grub_uint32_t offset;
|
||||
grub_uint32_t data_secs;
|
||||
char *override;
|
||||
ventoy_virt_chunk *cur;
|
||||
|
||||
override = (char *)chain + chain->virt_chunk_offset;
|
||||
cur = (ventoy_virt_chunk *)override;
|
||||
|
||||
sector = (isosize + 2047) / 2048;
|
||||
offset = 2 * sizeof(ventoy_virt_chunk);
|
||||
|
||||
if (g_conf_new_len > 0)
|
||||
{
|
||||
ventoy_unix_fill_virt(g_conf_new_data, g_conf_new_len);
|
||||
}
|
||||
|
||||
if (g_mod_new_len > 0)
|
||||
{
|
||||
ventoy_unix_fill_virt(g_mod_new_data, g_mod_new_len);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int ventoy_freebsd_append_conf(char *buf, const char *isopath)
|
||||
{
|
||||
int pos = 0;
|
||||
grub_uint32_t i;
|
||||
grub_disk_t disk;
|
||||
grub_file_t isofile;
|
||||
char uuid[64] = {0};
|
||||
ventoy_img_chunk *chunk;
|
||||
grub_uint8_t disk_guid[16];
|
||||
|
||||
debug("ventoy_freebsd_append_conf %s\n", isopath);
|
||||
|
||||
isofile = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", isopath);
|
||||
if (!isofile)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
vtoy_ssprintf(buf, pos, "ventoy_load=\"%s\"\n", "YES");
|
||||
vtoy_ssprintf(buf, pos, "ventoy_name=\"%s\"\n", g_ko_mod_path);
|
||||
|
||||
disk = isofile->device->disk;
|
||||
|
||||
ventoy_get_disk_guid(isofile->name, disk_guid);
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
grub_snprintf(uuid + i * 2, sizeof(uuid), "%02x", disk_guid[i]);
|
||||
}
|
||||
|
||||
vtoy_ssprintf(buf, pos, "hint.ventoy.0.disksize=%llu\n", (ulonglong)(disk->total_sectors * (1 << disk->log_sector_size)));
|
||||
vtoy_ssprintf(buf, pos, "hint.ventoy.0.diskuuid=\"%s\"\n", uuid);
|
||||
vtoy_ssprintf(buf, pos, "hint.ventoy.0.segnum=%u\n", g_img_chunk_list.cur_chunk);
|
||||
|
||||
for (i = 0; i < g_img_chunk_list.cur_chunk; i++)
|
||||
{
|
||||
chunk = g_img_chunk_list.chunk + i;
|
||||
vtoy_ssprintf(buf, pos, "hint.ventoy.%u.seg=\"0x%llx@0x%llx\"\n",
|
||||
i, (ulonglong)(chunk->disk_start_sector * 512),
|
||||
(ulonglong)((chunk->disk_end_sector + 1) * 512));
|
||||
}
|
||||
|
||||
grub_file_close(isofile);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_unix_reset(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
(void)ctxt;
|
||||
(void)argc;
|
||||
(void)args;
|
||||
|
||||
g_conf_new_len = 0;
|
||||
g_mod_new_len = 0;
|
||||
g_mod_override_offset = 0;
|
||||
g_conf_override_offset = 0;
|
||||
|
||||
check_free(g_mod_new_data, grub_free);
|
||||
check_free(g_conf_new_data, grub_free);
|
||||
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_parse_freenas_ver(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
grub_file_t file;
|
||||
const char *ver = NULL;
|
||||
char *buf = NULL;
|
||||
VTOY_JSON *json = NULL;
|
||||
|
||||
(void)ctxt;
|
||||
(void)argc;
|
||||
|
||||
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
|
||||
if (!file)
|
||||
{
|
||||
debug("Failed to open file %s\n", args[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
buf = grub_malloc(file->size + 2);
|
||||
if (!buf)
|
||||
{
|
||||
grub_file_close(file);
|
||||
return 0;
|
||||
}
|
||||
grub_file_read(file, buf, file->size);
|
||||
buf[file->size] = 0;
|
||||
|
||||
json = vtoy_json_create();
|
||||
if (!json)
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (vtoy_json_parse(json, buf))
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
|
||||
ver = vtoy_json_get_string_ex(json->pstChild, "Version");
|
||||
if (ver)
|
||||
{
|
||||
debug("freenas version:<%s>\n", ver);
|
||||
ventoy_set_env(args[1], ver);
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("freenas version:<%s>\n", "NOT FOUND");
|
||||
grub_env_unset(args[1]);
|
||||
}
|
||||
|
||||
end:
|
||||
grub_check_free(buf);
|
||||
check_free(json, vtoy_json_destroy);
|
||||
grub_file_close(file);
|
||||
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_unix_freebsd_ver(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
grub_file_t file;
|
||||
char *buf;
|
||||
char *start = NULL;
|
||||
char *nextline = NULL;
|
||||
|
||||
(void)ctxt;
|
||||
(void)argc;
|
||||
(void)args;
|
||||
|
||||
file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s", args[0]);
|
||||
if (!file)
|
||||
{
|
||||
debug("Failed to open file %s\n", args[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
buf = grub_zalloc(file->size + 2);
|
||||
if (!buf)
|
||||
{
|
||||
grub_file_close(file);
|
||||
return 0;
|
||||
}
|
||||
grub_file_read(file, buf, file->size);
|
||||
|
||||
for (start = buf; start; start = nextline)
|
||||
{
|
||||
if (grub_strncmp(start, "USERLAND_VERSION", 16) == 0)
|
||||
{
|
||||
nextline = start;
|
||||
while (*nextline && *nextline != '\r' && *nextline != '\n')
|
||||
{
|
||||
nextline++;
|
||||
}
|
||||
|
||||
*nextline = 0;
|
||||
break;
|
||||
}
|
||||
nextline = ventoy_get_line(start);
|
||||
}
|
||||
|
||||
if (start)
|
||||
{
|
||||
debug("freebsd version:<%s>\n", start);
|
||||
ventoy_set_env(args[1], start);
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("freebsd version:<%s>\n", "NOT FOUND");
|
||||
grub_env_unset(args[1]);
|
||||
}
|
||||
|
||||
grub_free(buf);
|
||||
grub_file_close(file);
|
||||
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_unix_replace_conf(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
grub_uint32_t i;
|
||||
char *data;
|
||||
grub_uint64_t offset;
|
||||
grub_file_t file;
|
||||
const char *confile = NULL;
|
||||
const char * loader_conf[] =
|
||||
{
|
||||
"/boot/loader.conf",
|
||||
"/boot/defaults/loader.conf",
|
||||
};
|
||||
|
||||
(void)ctxt;
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
debug("Replace conf invalid argc %d\n", argc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(loader_conf) / sizeof(loader_conf[0]); i++)
|
||||
{
|
||||
if (ventoy_get_file_override(loader_conf[i], &offset) == 0)
|
||||
{
|
||||
confile = loader_conf[i];
|
||||
g_conf_override_offset = offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (confile == NULL)
|
||||
{
|
||||
debug("Can't find loader.conf file from %u locations\n", i);
|
||||
return 1;
|
||||
}
|
||||
|
||||
file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "(loop)/%s", confile);
|
||||
if (!file)
|
||||
{
|
||||
debug("Failed to open %s \n", confile);
|
||||
return 1;
|
||||
}
|
||||
|
||||
debug("old conf file size:%d\n", (int)file->size);
|
||||
|
||||
data = grub_malloc(VTOY_MAX_SCRIPT_BUF);
|
||||
if (!data)
|
||||
{
|
||||
grub_file_close(file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
grub_file_read(file, data, file->size);
|
||||
grub_file_close(file);
|
||||
|
||||
g_conf_new_data = data;
|
||||
g_conf_new_len = (int)file->size;
|
||||
|
||||
if (grub_strcmp(args[0], "FreeBSD") == 0)
|
||||
{
|
||||
g_conf_new_len += ventoy_freebsd_append_conf(data + file->size, args[1]);
|
||||
}
|
||||
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_unix_replace_ko(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
char *data;
|
||||
grub_uint64_t offset;
|
||||
grub_file_t file;
|
||||
|
||||
(void)ctxt;
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
debug("Replace ko invalid argc %d\n", argc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
debug("replace ko %s\n", args[0]);
|
||||
|
||||
if (ventoy_get_file_override(args[0], &offset) == 0)
|
||||
{
|
||||
grub_snprintf(g_ko_mod_path, sizeof(g_ko_mod_path), "%s", args[0]);
|
||||
g_mod_override_offset = offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("Can't find replace ko file from %s\n", args[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s", args[1]);
|
||||
if (!file)
|
||||
{
|
||||
debug("Failed to open %s \n", args[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
debug("new ko file size:%d\n", (int)file->size);
|
||||
|
||||
data = grub_malloc(file->size);
|
||||
if (!data)
|
||||
{
|
||||
grub_file_close(file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
grub_file_read(file, data, file->size);
|
||||
grub_file_close(file);
|
||||
|
||||
g_mod_new_data = data;
|
||||
g_mod_new_len = (int)file->size;
|
||||
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_unix_chain_data(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
int ventoy_compatible = 0;
|
||||
grub_uint32_t size = 0;
|
||||
grub_uint64_t isosize = 0;
|
||||
grub_uint32_t boot_catlog = 0;
|
||||
grub_uint32_t img_chunk_size = 0;
|
||||
grub_uint32_t override_count = 0;
|
||||
grub_uint32_t override_size = 0;
|
||||
grub_uint32_t virt_chunk_size = 0;
|
||||
grub_file_t file;
|
||||
grub_disk_t disk;
|
||||
const char *pLastChain = NULL;
|
||||
const char *compatible;
|
||||
ventoy_chain_head *chain;
|
||||
char envbuf[64];
|
||||
|
||||
(void)ctxt;
|
||||
(void)argc;
|
||||
|
||||
compatible = grub_env_get("ventoy_compatible");
|
||||
if (compatible && compatible[0] == 'Y')
|
||||
{
|
||||
ventoy_compatible = 1;
|
||||
}
|
||||
|
||||
if (NULL == g_img_chunk_list.chunk)
|
||||
{
|
||||
grub_printf("ventoy not ready\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
|
||||
if (!file)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
isosize = file->size;
|
||||
|
||||
boot_catlog = ventoy_get_iso_boot_catlog(file);
|
||||
if (boot_catlog)
|
||||
{
|
||||
if (ventoy_is_efi_os() && (!ventoy_has_efi_eltorito(file, boot_catlog)))
|
||||
{
|
||||
grub_env_set("LoadIsoEfiDriver", "on");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ventoy_is_efi_os())
|
||||
{
|
||||
grub_env_set("LoadIsoEfiDriver", "on");
|
||||
}
|
||||
else
|
||||
{
|
||||
return grub_error(GRUB_ERR_BAD_ARGUMENT, "File %s is not bootable", args[0]);
|
||||
}
|
||||
}
|
||||
|
||||
img_chunk_size = g_img_chunk_list.cur_chunk * sizeof(ventoy_img_chunk);
|
||||
|
||||
if (ventoy_compatible)
|
||||
{
|
||||
size = sizeof(ventoy_chain_head) + img_chunk_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
override_count = ventoy_unix_get_override_chunk_count();
|
||||
override_size = override_count * sizeof(ventoy_override_chunk);
|
||||
|
||||
virt_chunk_size = ventoy_unix_get_virt_chunk_size();
|
||||
size = sizeof(ventoy_chain_head) + img_chunk_size + override_size + virt_chunk_size;
|
||||
}
|
||||
|
||||
pLastChain = grub_env_get("vtoy_chain_mem_addr");
|
||||
if (pLastChain)
|
||||
{
|
||||
chain = (ventoy_chain_head *)grub_strtoul(pLastChain, NULL, 16);
|
||||
if (chain)
|
||||
{
|
||||
debug("free last chain memory %p\n", chain);
|
||||
grub_free(chain);
|
||||
}
|
||||
}
|
||||
|
||||
chain = grub_malloc(size);
|
||||
if (!chain)
|
||||
{
|
||||
grub_printf("Failed to alloc chain memory size %u\n", size);
|
||||
grub_file_close(file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
grub_snprintf(envbuf, sizeof(envbuf), "0x%lx", (unsigned long)chain);
|
||||
grub_env_set("vtoy_chain_mem_addr", envbuf);
|
||||
grub_snprintf(envbuf, sizeof(envbuf), "%u", size);
|
||||
grub_env_set("vtoy_chain_mem_size", envbuf);
|
||||
|
||||
grub_memset(chain, 0, sizeof(ventoy_chain_head));
|
||||
|
||||
/* part 1: os parameter */
|
||||
g_ventoy_chain_type = ventoy_chain_linux;
|
||||
ventoy_fill_os_param(file, &(chain->os_param));
|
||||
|
||||
/* part 2: chain head */
|
||||
disk = file->device->disk;
|
||||
chain->disk_drive = disk->id;
|
||||
chain->disk_sector_size = (1 << disk->log_sector_size);
|
||||
chain->real_img_size_in_bytes = file->size;
|
||||
chain->virt_img_size_in_bytes = (file->size + 2047) / 2048 * 2048;
|
||||
chain->boot_catalog = boot_catlog;
|
||||
|
||||
if (!ventoy_is_efi_os())
|
||||
{
|
||||
grub_file_seek(file, boot_catlog * 2048);
|
||||
grub_file_read(file, chain->boot_catalog_sector, sizeof(chain->boot_catalog_sector));
|
||||
}
|
||||
|
||||
/* part 3: image chunk */
|
||||
chain->img_chunk_offset = sizeof(ventoy_chain_head);
|
||||
chain->img_chunk_num = g_img_chunk_list.cur_chunk;
|
||||
grub_memcpy((char *)chain + chain->img_chunk_offset, g_img_chunk_list.chunk, img_chunk_size);
|
||||
|
||||
if (ventoy_compatible)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* part 4: override chunk */
|
||||
chain->override_chunk_offset = chain->img_chunk_offset + img_chunk_size;
|
||||
chain->override_chunk_num = override_count;
|
||||
ventoy_unix_fill_override_data(isosize, (char *)chain + chain->override_chunk_offset);
|
||||
|
||||
/* part 5: virt chunk */
|
||||
chain->virt_chunk_offset = chain->override_chunk_offset + override_size;
|
||||
chain->virt_chunk_num = ventoy_unix_get_virt_chunk_count();
|
||||
ventoy_unix_fill_virt_data(isosize, chain);
|
||||
|
||||
grub_file_close(file);
|
||||
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
1700
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_windows.c
Normal file
1700
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_windows.c
Normal file
File diff suppressed because it is too large
Load Diff
157
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/xpress.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
87
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/xpress.h
Normal file
@@ -0,0 +1,87 @@
|
||||
#ifndef _XCA_H
|
||||
#define _XCA_H
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Xpress Compression Algorithm (MS-XCA) decompression
|
||||
*
|
||||
*/
|
||||
|
||||
#include "huffman.h"
|
||||
|
||||
/** Number of XCA codes */
|
||||
#define XCA_CODES 512
|
||||
|
||||
/** XCA decompressor */
|
||||
struct xca {
|
||||
/** Huffman alphabet */
|
||||
struct huffman_alphabet alphabet;
|
||||
/** Raw symbols
|
||||
*
|
||||
* Must immediately follow the Huffman alphabet.
|
||||
*/
|
||||
huffman_raw_symbol_t raw[XCA_CODES];
|
||||
/** Code lengths */
|
||||
uint8_t lengths[XCA_CODES];
|
||||
};
|
||||
|
||||
/** XCA symbol Huffman lengths table */
|
||||
struct xca_huf_len {
|
||||
/** Lengths of each symbol */
|
||||
uint8_t nibbles[ XCA_CODES / 2 ];
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/**
|
||||
* Extract Huffman-coded length of a raw symbol
|
||||
*
|
||||
* @v lengths Huffman lengths table
|
||||
* @v symbol Raw symbol
|
||||
* @ret len Huffman-coded length
|
||||
*/
|
||||
static inline unsigned int xca_huf_len ( const struct xca_huf_len *lengths,
|
||||
unsigned int symbol ) {
|
||||
return ( ( ( lengths->nibbles[ symbol / 2 ] ) >>
|
||||
( 4 * ( symbol % 2 ) ) ) & 0x0f );
|
||||
}
|
||||
|
||||
/** Get word from source data stream */
|
||||
#define XCA_GET16( src ) ( { \
|
||||
const uint16_t *src16 = src; \
|
||||
src = ( uint8_t * ) src + sizeof ( *src16 ); \
|
||||
*src16; } )
|
||||
|
||||
/** Get byte from source data stream */
|
||||
#define XCA_GET8( src ) ( { \
|
||||
const uint8_t *src8 = src; \
|
||||
src = ( uint8_t * ) src + sizeof ( *src8 ); \
|
||||
*src8; } )
|
||||
|
||||
/** XCA source data stream end marker */
|
||||
#define XCA_END_MARKER 256
|
||||
|
||||
/** XCA block size */
|
||||
#define XCA_BLOCK_SIZE ( 64 * 1024 )
|
||||
|
||||
extern ssize_t xca_decompress ( const void *data, size_t len, void *buf );
|
||||
|
||||
#endif /* _XCA_H */
|
53
GRUB2/MOD_SRC/grub-2.04/include/grub/compiler.h
Normal file
53
GRUB2/MOD_SRC/grub-2.04/include/grub/compiler.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/* compiler.h - macros for various compiler features */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2002,2003,2005,2006,2007,2008,2009,2010,2014 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GRUB_COMPILER_HEADER
|
||||
#define GRUB_COMPILER_HEADER 1
|
||||
|
||||
/* GCC version checking borrowed from glibc. */
|
||||
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
|
||||
# define GNUC_PREREQ(maj,min) \
|
||||
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
|
||||
#else
|
||||
# define GNUC_PREREQ(maj,min) 0
|
||||
#endif
|
||||
|
||||
/* Does this compiler support compile-time error attributes? */
|
||||
#if GNUC_PREREQ(4,3)
|
||||
# define ATTRIBUTE_ERROR(msg) \
|
||||
__attribute__ ((__error__ (msg)))
|
||||
#else
|
||||
# define ATTRIBUTE_ERROR(msg) __attribute__ ((noreturn))
|
||||
#endif
|
||||
|
||||
#if GNUC_PREREQ(4,4)
|
||||
# define GNU_PRINTF gnu_printf
|
||||
#else
|
||||
# define GNU_PRINTF printf
|
||||
#endif
|
||||
|
||||
#if GNUC_PREREQ(3,4)
|
||||
# define WARN_UNUSED_RESULT __attribute__ ((warn_unused_result))
|
||||
#else
|
||||
# define WARN_UNUSED_RESULT
|
||||
#endif
|
||||
|
||||
#define UNUSED __attribute__((__unused__))
|
||||
|
||||
#endif /* ! GRUB_COMPILER_HEADER */
|
243
GRUB2/MOD_SRC/grub-2.04/include/grub/file.h
Normal file
243
GRUB2/MOD_SRC/grub-2.04/include/grub/file.h
Normal file
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2002,2007 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GRUB_FILE_HEADER
|
||||
#define GRUB_FILE_HEADER 1
|
||||
|
||||
#include <grub/types.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/device.h>
|
||||
#include <grub/fs.h>
|
||||
#include <grub/disk.h>
|
||||
|
||||
enum grub_file_type
|
||||
{
|
||||
GRUB_FILE_TYPE_NONE = 0,
|
||||
/* GRUB module to be loaded. */
|
||||
GRUB_FILE_TYPE_GRUB_MODULE,
|
||||
/* Loopback file to be represented as disk. */
|
||||
GRUB_FILE_TYPE_LOOPBACK,
|
||||
/* Linux kernel to be loaded. */
|
||||
GRUB_FILE_TYPE_LINUX_KERNEL,
|
||||
/* Linux initrd. */
|
||||
GRUB_FILE_TYPE_LINUX_INITRD,
|
||||
|
||||
/* Multiboot kernel. */
|
||||
GRUB_FILE_TYPE_MULTIBOOT_KERNEL,
|
||||
/* Multiboot module. */
|
||||
GRUB_FILE_TYPE_MULTIBOOT_MODULE,
|
||||
|
||||
/* Xen hypervisor - used on ARM only. */
|
||||
GRUB_FILE_TYPE_XEN_HYPERVISOR,
|
||||
/* Xen module - used on ARM only. */
|
||||
GRUB_FILE_TYPE_XEN_MODULE,
|
||||
|
||||
GRUB_FILE_TYPE_BSD_KERNEL,
|
||||
GRUB_FILE_TYPE_FREEBSD_ENV,
|
||||
GRUB_FILE_TYPE_FREEBSD_MODULE,
|
||||
GRUB_FILE_TYPE_FREEBSD_MODULE_ELF,
|
||||
GRUB_FILE_TYPE_NETBSD_MODULE,
|
||||
GRUB_FILE_TYPE_OPENBSD_RAMDISK,
|
||||
|
||||
GRUB_FILE_TYPE_XNU_INFO_PLIST,
|
||||
GRUB_FILE_TYPE_XNU_MKEXT,
|
||||
GRUB_FILE_TYPE_XNU_KEXT,
|
||||
GRUB_FILE_TYPE_XNU_KERNEL,
|
||||
GRUB_FILE_TYPE_XNU_RAMDISK,
|
||||
GRUB_FILE_TYPE_XNU_HIBERNATE_IMAGE,
|
||||
GRUB_FILE_XNU_DEVPROP,
|
||||
|
||||
GRUB_FILE_TYPE_PLAN9_KERNEL,
|
||||
|
||||
GRUB_FILE_TYPE_NTLDR,
|
||||
GRUB_FILE_TYPE_TRUECRYPT,
|
||||
GRUB_FILE_TYPE_FREEDOS,
|
||||
GRUB_FILE_TYPE_PXECHAINLOADER,
|
||||
GRUB_FILE_TYPE_PCCHAINLOADER,
|
||||
|
||||
GRUB_FILE_TYPE_COREBOOT_CHAINLOADER,
|
||||
|
||||
GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE,
|
||||
|
||||
/* File holding signature. */
|
||||
GRUB_FILE_TYPE_SIGNATURE,
|
||||
/* File holding public key to verify signature once. */
|
||||
GRUB_FILE_TYPE_PUBLIC_KEY,
|
||||
/* File holding public key to add to trused keys. */
|
||||
GRUB_FILE_TYPE_PUBLIC_KEY_TRUST,
|
||||
/* File of which we intend to print a blocklist to the user. */
|
||||
GRUB_FILE_TYPE_PRINT_BLOCKLIST,
|
||||
/* File we intend to use for test loading or testing speed. */
|
||||
GRUB_FILE_TYPE_TESTLOAD,
|
||||
/* File we open only to get its size. E.g. in ls output. */
|
||||
GRUB_FILE_TYPE_GET_SIZE,
|
||||
/* Font file. */
|
||||
GRUB_FILE_TYPE_FONT,
|
||||
/* File holding encryption key for encrypted ZFS. */
|
||||
GRUB_FILE_TYPE_ZFS_ENCRYPTION_KEY,
|
||||
/* File we open n grub-fstest. */
|
||||
GRUB_FILE_TYPE_FSTEST,
|
||||
/* File we open n grub-mount. */
|
||||
GRUB_FILE_TYPE_MOUNT,
|
||||
/* File which we attempt to identify the type of. */
|
||||
GRUB_FILE_TYPE_FILE_ID,
|
||||
/* File holding ACPI table. */
|
||||
GRUB_FILE_TYPE_ACPI_TABLE,
|
||||
/* File holding Device Tree. */
|
||||
GRUB_FILE_TYPE_DEVICE_TREE_IMAGE,
|
||||
/* File we intend show to user. */
|
||||
GRUB_FILE_TYPE_CAT,
|
||||
GRUB_FILE_TYPE_HEXCAT,
|
||||
/* One of pair of files we intend to compare. */
|
||||
GRUB_FILE_TYPE_CMP,
|
||||
/* List of hashes for hashsum. */
|
||||
GRUB_FILE_TYPE_HASHLIST,
|
||||
/* File hashed by hashsum. */
|
||||
GRUB_FILE_TYPE_TO_HASH,
|
||||
/* Keyboard layout. */
|
||||
GRUB_FILE_TYPE_KEYBOARD_LAYOUT,
|
||||
/* Picture file. */
|
||||
GRUB_FILE_TYPE_PIXMAP,
|
||||
/* *.lst shipped by GRUB. */
|
||||
GRUB_FILE_TYPE_GRUB_MODULE_LIST,
|
||||
/* config file. */
|
||||
GRUB_FILE_TYPE_CONFIG,
|
||||
GRUB_FILE_TYPE_THEME,
|
||||
GRUB_FILE_TYPE_GETTEXT_CATALOG,
|
||||
GRUB_FILE_TYPE_FS_SEARCH,
|
||||
GRUB_FILE_TYPE_AUDIO,
|
||||
GRUB_FILE_TYPE_VBE_DUMP,
|
||||
|
||||
GRUB_FILE_TYPE_LOADENV,
|
||||
GRUB_FILE_TYPE_SAVEENV,
|
||||
|
||||
GRUB_FILE_TYPE_VERIFY_SIGNATURE,
|
||||
|
||||
GRUB_FILE_TYPE_MASK = 0xffff,
|
||||
|
||||
/* --skip-sig is specified. */
|
||||
GRUB_FILE_TYPE_SKIP_SIGNATURE = 0x10000,
|
||||
GRUB_FILE_TYPE_NO_DECOMPRESS = 0x20000
|
||||
};
|
||||
|
||||
/* File description. */
|
||||
struct grub_file
|
||||
{
|
||||
/* File name. */
|
||||
char *name;
|
||||
|
||||
/* The underlying device. */
|
||||
grub_device_t device;
|
||||
|
||||
/* The underlying filesystem. */
|
||||
grub_fs_t fs;
|
||||
|
||||
/* The current offset. */
|
||||
grub_off_t offset;
|
||||
grub_off_t progress_offset;
|
||||
|
||||
/* Progress info. */
|
||||
grub_uint64_t last_progress_time;
|
||||
grub_off_t last_progress_offset;
|
||||
grub_uint64_t estimated_speed;
|
||||
|
||||
/* The file size. */
|
||||
grub_off_t size;
|
||||
|
||||
/* If file is not easily seekable. Should be set by underlying layer. */
|
||||
int not_easily_seekable;
|
||||
|
||||
/* Filesystem-specific data. */
|
||||
void *data;
|
||||
|
||||
/* This is called when a sector is read. Used only for a disk device. */
|
||||
grub_disk_read_hook_t read_hook;
|
||||
|
||||
/* Caller-specific data passed to the read hook. */
|
||||
void *read_hook_data;
|
||||
};
|
||||
typedef struct grub_file *grub_file_t;
|
||||
|
||||
extern grub_disk_read_hook_t EXPORT_VAR(grub_file_progress_hook);
|
||||
|
||||
/* Filters with lower ID are executed first. */
|
||||
typedef enum grub_file_filter_id
|
||||
{
|
||||
GRUB_FILE_FILTER_VERIFY,
|
||||
GRUB_FILE_FILTER_GZIO,
|
||||
GRUB_FILE_FILTER_XZIO,
|
||||
GRUB_FILE_FILTER_LZOPIO,
|
||||
GRUB_FILE_FILTER_MAX,
|
||||
GRUB_FILE_FILTER_COMPRESSION_FIRST = GRUB_FILE_FILTER_GZIO,
|
||||
GRUB_FILE_FILTER_COMPRESSION_LAST = GRUB_FILE_FILTER_LZOPIO,
|
||||
} grub_file_filter_id_t;
|
||||
|
||||
typedef grub_file_t (*grub_file_filter_t) (grub_file_t in, enum grub_file_type type);
|
||||
|
||||
extern grub_file_filter_t EXPORT_VAR(grub_file_filters)[GRUB_FILE_FILTER_MAX];
|
||||
|
||||
static inline void
|
||||
grub_file_filter_register (grub_file_filter_id_t id, grub_file_filter_t filter)
|
||||
{
|
||||
grub_file_filters[id] = filter;
|
||||
}
|
||||
|
||||
static inline void
|
||||
grub_file_filter_unregister (grub_file_filter_id_t id)
|
||||
{
|
||||
grub_file_filters[id] = 0;
|
||||
}
|
||||
|
||||
/* Get a device name from NAME. */
|
||||
char *EXPORT_FUNC(grub_file_get_device_name) (const char *name);
|
||||
|
||||
int EXPORT_FUNC(ventoy_check_file_exist) (const char * fmt, ...);
|
||||
grub_file_t EXPORT_FUNC(grub_file_open) (const char *name, enum grub_file_type type);
|
||||
grub_ssize_t EXPORT_FUNC(grub_file_read) (grub_file_t file, void *buf,
|
||||
grub_size_t len);
|
||||
grub_off_t EXPORT_FUNC(grub_file_seek) (grub_file_t file, grub_off_t offset);
|
||||
grub_err_t EXPORT_FUNC(grub_file_close) (grub_file_t file);
|
||||
|
||||
/* Return value of grub_file_size() in case file size is unknown. */
|
||||
#define GRUB_FILE_SIZE_UNKNOWN 0xffffffffffffffffULL
|
||||
|
||||
static inline grub_off_t
|
||||
grub_file_size (const grub_file_t file)
|
||||
{
|
||||
return file->size;
|
||||
}
|
||||
|
||||
static inline grub_off_t
|
||||
grub_file_tell (const grub_file_t file)
|
||||
{
|
||||
return file->offset;
|
||||
}
|
||||
|
||||
static inline int
|
||||
grub_file_seekable (const grub_file_t file)
|
||||
{
|
||||
return !file->not_easily_seekable;
|
||||
}
|
||||
|
||||
grub_file_t
|
||||
grub_file_offset_open (grub_file_t parent, enum grub_file_type type,
|
||||
grub_off_t start, grub_off_t size);
|
||||
void
|
||||
grub_file_offset_close (grub_file_t file);
|
||||
|
||||
#endif /* ! GRUB_FILE_HEADER */
|
133
GRUB2/MOD_SRC/grub-2.04/include/grub/kernel.h
Normal file
133
GRUB2/MOD_SRC/grub-2.04/include/grub/kernel.h
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2002,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GRUB_KERNEL_HEADER
|
||||
#define GRUB_KERNEL_HEADER 1
|
||||
|
||||
#include <grub/types.h>
|
||||
#include <grub/symbol.h>
|
||||
|
||||
enum
|
||||
{
|
||||
OBJ_TYPE_ELF,
|
||||
OBJ_TYPE_MEMDISK,
|
||||
OBJ_TYPE_CONFIG,
|
||||
OBJ_TYPE_PREFIX,
|
||||
OBJ_TYPE_PUBKEY,
|
||||
OBJ_TYPE_DTB
|
||||
};
|
||||
|
||||
/* The module header. */
|
||||
struct grub_module_header
|
||||
{
|
||||
/* The type of object. */
|
||||
grub_uint32_t type;
|
||||
/* The size of object (including this header). */
|
||||
grub_uint32_t size;
|
||||
};
|
||||
|
||||
/* "gmim" (GRUB Module Info Magic). */
|
||||
#define GRUB_MODULE_MAGIC 0x676d696d
|
||||
|
||||
struct grub_module_info32
|
||||
{
|
||||
/* Magic number so we know we have modules present. */
|
||||
grub_uint32_t magic;
|
||||
/* The offset of the modules. */
|
||||
grub_uint32_t offset;
|
||||
/* The size of all modules plus this header. */
|
||||
grub_uint32_t size;
|
||||
};
|
||||
|
||||
struct grub_module_info64
|
||||
{
|
||||
/* Magic number so we know we have modules present. */
|
||||
grub_uint32_t magic;
|
||||
grub_uint32_t padding;
|
||||
/* The offset of the modules. */
|
||||
grub_uint64_t offset;
|
||||
/* The size of all modules plus this header. */
|
||||
grub_uint64_t size;
|
||||
};
|
||||
|
||||
#ifndef GRUB_UTIL
|
||||
/* Space isn't reusable on some platforms. */
|
||||
/* On Qemu the preload space is readonly. */
|
||||
/* On emu there is no preload space. */
|
||||
/* On ieee1275 our code assumes that heap is p=v which isn't guaranteed for module space. */
|
||||
#if defined (GRUB_MACHINE_QEMU) || defined (GRUB_MACHINE_EMU) \
|
||||
|| defined (GRUB_MACHINE_EFI) \
|
||||
|| (defined (GRUB_MACHINE_IEEE1275) && !defined (__sparc__))
|
||||
#define GRUB_KERNEL_PRELOAD_SPACE_REUSABLE 0
|
||||
#endif
|
||||
|
||||
#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) \
|
||||
|| defined (GRUB_MACHINE_MULTIBOOT) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS) \
|
||||
|| defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_ARC) \
|
||||
|| (defined (__sparc__) && defined (GRUB_MACHINE_IEEE1275)) \
|
||||
|| defined (GRUB_MACHINE_UBOOT) || defined (GRUB_MACHINE_XEN) \
|
||||
|| defined(GRUB_MACHINE_XEN_PVH)
|
||||
/* FIXME: stack is between 2 heap regions. Move it. */
|
||||
#define GRUB_KERNEL_PRELOAD_SPACE_REUSABLE 1
|
||||
#endif
|
||||
|
||||
#ifndef GRUB_KERNEL_PRELOAD_SPACE_REUSABLE
|
||||
#error "Please check if preload space is reusable on this platform!"
|
||||
#endif
|
||||
|
||||
#if GRUB_TARGET_SIZEOF_VOID_P == 8
|
||||
#define grub_module_info grub_module_info64
|
||||
#else
|
||||
#define grub_module_info grub_module_info32
|
||||
#endif
|
||||
|
||||
extern grub_addr_t EXPORT_VAR (grub_modbase);
|
||||
|
||||
void EXPORT_FUNC(ventoy_env_hook_root)(int hook);
|
||||
|
||||
#define FOR_MODULES(var) for (\
|
||||
var = (grub_modbase && ((((struct grub_module_info *) grub_modbase)->magic) == GRUB_MODULE_MAGIC)) ? (struct grub_module_header *) \
|
||||
(grub_modbase + (((struct grub_module_info *) grub_modbase)->offset)) : 0;\
|
||||
var && (grub_addr_t) var \
|
||||
< (grub_modbase + (((struct grub_module_info *) grub_modbase)->size)); \
|
||||
var = (struct grub_module_header *) \
|
||||
(((grub_uint32_t *) var) + ((((struct grub_module_header *) var)->size + sizeof (grub_addr_t) - 1) / sizeof (grub_addr_t)) * (sizeof (grub_addr_t) / sizeof (grub_uint32_t))))
|
||||
|
||||
grub_addr_t grub_modules_get_end (void);
|
||||
|
||||
#endif
|
||||
|
||||
/* The start point of the C code. */
|
||||
void grub_main (void) __attribute__ ((noreturn));
|
||||
|
||||
/* The machine-specific initialization. This must initialize memory. */
|
||||
void grub_machine_init (void);
|
||||
|
||||
/* The machine-specific finalization. */
|
||||
void EXPORT_FUNC(grub_machine_fini) (int flags);
|
||||
|
||||
/* The machine-specific prefix initialization. */
|
||||
void
|
||||
grub_machine_get_bootlocation (char **device, char **path);
|
||||
|
||||
/* Register all the exported symbols. This is automatically generated. */
|
||||
void grub_register_exported_symbols (void);
|
||||
|
||||
extern void (*EXPORT_VAR(grub_net_poll_cards_idle)) (void);
|
||||
|
||||
#endif /* ! GRUB_KERNEL_HEADER */
|
119
GRUB2/MOD_SRC/grub-2.04/include/grub/menu.h
Normal file
119
GRUB2/MOD_SRC/grub-2.04/include/grub/menu.h
Normal file
@@ -0,0 +1,119 @@
|
||||
/* menu.h - Menu model function prototypes and data structures. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GRUB_MENU_HEADER
|
||||
#define GRUB_MENU_HEADER 1
|
||||
|
||||
struct bls_entry
|
||||
{
|
||||
struct bls_entry *next;
|
||||
struct bls_entry *prev;
|
||||
struct keyval **keyvals;
|
||||
int nkeyvals;
|
||||
char *filename;
|
||||
int visible;
|
||||
};
|
||||
|
||||
struct grub_menu_entry_class
|
||||
{
|
||||
char *name;
|
||||
struct grub_menu_entry_class *next;
|
||||
};
|
||||
|
||||
/* The menu entry. */
|
||||
struct grub_menu_entry
|
||||
{
|
||||
/* The title name. */
|
||||
const char *title;
|
||||
|
||||
/* The identifier. */
|
||||
const char *id;
|
||||
|
||||
/* If set means not everybody is allowed to boot this entry. */
|
||||
int restricted;
|
||||
|
||||
/* Allowed users. */
|
||||
const char *users;
|
||||
|
||||
/* The classes associated with the menu entry:
|
||||
used to choose an icon or other style attributes.
|
||||
This is a dummy head node for the linked list, so for an entry E,
|
||||
E.classes->next is the first class if it is not NULL. */
|
||||
struct grub_menu_entry_class *classes;
|
||||
|
||||
/* The sourcecode of the menu entry, used by the editor. */
|
||||
const char *sourcecode;
|
||||
|
||||
/* Parameters to be passed to menu definition. */
|
||||
int argc;
|
||||
char **args;
|
||||
|
||||
int hotkey;
|
||||
|
||||
int submenu;
|
||||
|
||||
/* The next element. */
|
||||
struct grub_menu_entry *next;
|
||||
|
||||
/* BLS used to populate the entry */
|
||||
struct bls_entry *bls;
|
||||
};
|
||||
typedef struct grub_menu_entry *grub_menu_entry_t;
|
||||
|
||||
/* The menu. */
|
||||
struct grub_menu
|
||||
{
|
||||
/* The size of a menu. */
|
||||
int size;
|
||||
|
||||
/* The list of menu entries. */
|
||||
grub_menu_entry_t entry_list;
|
||||
};
|
||||
typedef struct grub_menu *grub_menu_t;
|
||||
|
||||
/* Callback structure menu viewers can use to provide user feedback when
|
||||
default entries are executed, possibly including fallback entries. */
|
||||
typedef struct grub_menu_execute_callback
|
||||
{
|
||||
/* Called immediately before ENTRY is booted. */
|
||||
void (*notify_booting) (grub_menu_entry_t entry, void *userdata);
|
||||
|
||||
/* Called when executing one entry has failed, and another entry, ENTRY, will
|
||||
be executed as a fallback. The implementation of this function should
|
||||
delay for a period of at least 2 seconds before returning in order to
|
||||
allow the user time to read the information before it can be lost by
|
||||
executing ENTRY. */
|
||||
void (*notify_fallback) (grub_menu_entry_t entry, void *userdata);
|
||||
|
||||
/* Called when an entry has failed to execute and there is no remaining
|
||||
fallback entry to attempt. */
|
||||
void (*notify_failure) (void *userdata);
|
||||
}
|
||||
*grub_menu_execute_callback_t;
|
||||
|
||||
grub_menu_entry_t grub_menu_get_entry (grub_menu_t menu, int no);
|
||||
int grub_menu_get_timeout (void);
|
||||
void grub_menu_set_timeout (int timeout);
|
||||
void grub_menu_entry_run (grub_menu_entry_t entry);
|
||||
int grub_menu_get_default_entry_index (grub_menu_t menu);
|
||||
|
||||
void grub_menu_init (void);
|
||||
void grub_menu_fini (void);
|
||||
|
||||
#endif /* GRUB_MENU_HEADER */
|
177
GRUB2/MOD_SRC/grub-2.04/include/grub/normal.h
Normal file
177
GRUB2/MOD_SRC/grub-2.04/include/grub/normal.h
Normal file
@@ -0,0 +1,177 @@
|
||||
/* normal.h - prototypes for the normal mode */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2002,2003,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GRUB_NORMAL_HEADER
|
||||
#define GRUB_NORMAL_HEADER 1
|
||||
|
||||
#include <grub/term.h>
|
||||
#include <grub/symbol.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/menu.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/file.h>
|
||||
|
||||
/* The standard left and right margin for some messages. */
|
||||
#define STANDARD_MARGIN 6
|
||||
|
||||
/* The type of a completion item. */
|
||||
enum grub_completion_type
|
||||
{
|
||||
GRUB_COMPLETION_TYPE_COMMAND,
|
||||
GRUB_COMPLETION_TYPE_DEVICE,
|
||||
GRUB_COMPLETION_TYPE_PARTITION,
|
||||
GRUB_COMPLETION_TYPE_FILE,
|
||||
GRUB_COMPLETION_TYPE_ARGUMENT
|
||||
};
|
||||
typedef enum grub_completion_type grub_completion_type_t;
|
||||
|
||||
extern struct grub_menu_viewer grub_normal_text_menu_viewer;
|
||||
extern int grub_normal_exit_level;
|
||||
|
||||
/* Defined in `main.c'. */
|
||||
void grub_enter_normal_mode (const char *config);
|
||||
void grub_normal_execute (const char *config, int nested, int batch);
|
||||
struct grub_term_screen_geometry
|
||||
{
|
||||
/* The number of entries shown at a time. */
|
||||
int num_entries;
|
||||
int first_entry_y;
|
||||
int first_entry_x;
|
||||
int entry_width;
|
||||
int timeout_y;
|
||||
int timeout_lines;
|
||||
int border;
|
||||
int right_margin;
|
||||
};
|
||||
|
||||
void grub_menu_init_page (int nested, int edit,
|
||||
struct grub_term_screen_geometry *geo,
|
||||
struct grub_term_output *term);
|
||||
void grub_normal_init_page (struct grub_term_output *term, int y);
|
||||
char *grub_file_getline (grub_file_t file);
|
||||
void grub_cmdline_run (int nested, int force_auth);
|
||||
|
||||
/* Defined in `cmdline.c'. */
|
||||
char *grub_cmdline_get (const char *prompt);
|
||||
grub_err_t grub_set_history (int newsize);
|
||||
|
||||
/* Defined in `completion.c'. */
|
||||
char *grub_normal_do_completion (char *buf, int *restore,
|
||||
void (*hook) (const char *item, grub_completion_type_t type, int count));
|
||||
|
||||
/* Defined in `misc.c'. */
|
||||
grub_err_t grub_normal_print_device_info (const char *name);
|
||||
|
||||
/* Defined in `color.c'. */
|
||||
char *grub_env_write_color_normal (struct grub_env_var *var, const char *val);
|
||||
char *grub_env_write_color_highlight (struct grub_env_var *var, const char *val);
|
||||
int grub_parse_color_name_pair (grub_uint8_t *ret, const char *name);
|
||||
|
||||
/* Defined in `menu_text.c'. */
|
||||
void grub_wait_after_message (void);
|
||||
void
|
||||
grub_print_ucs4 (const grub_uint32_t * str,
|
||||
const grub_uint32_t * last_position,
|
||||
int margin_left, int margin_right,
|
||||
struct grub_term_output *term);
|
||||
|
||||
void
|
||||
grub_print_ucs4_menu (const grub_uint32_t * str,
|
||||
const grub_uint32_t * last_position,
|
||||
int margin_left, int margin_right,
|
||||
struct grub_term_output *term,
|
||||
int skip_lines, int max_lines, grub_uint32_t contchar,
|
||||
struct grub_term_pos *pos);
|
||||
int
|
||||
grub_ucs4_count_lines (const grub_uint32_t * str,
|
||||
const grub_uint32_t * last_position,
|
||||
int margin_left, int margin_right,
|
||||
struct grub_term_output *term);
|
||||
grub_size_t grub_getstringwidth (grub_uint32_t * str,
|
||||
const grub_uint32_t * last_position,
|
||||
struct grub_term_output *term);
|
||||
void grub_print_message_indented (const char *msg, int margin_left,
|
||||
int margin_right,
|
||||
struct grub_term_output *term);
|
||||
void
|
||||
grub_menu_text_register_instances (int entry, grub_menu_t menu, int nested);
|
||||
grub_err_t
|
||||
grub_show_menu (grub_menu_t menu, int nested, int autobooted);
|
||||
|
||||
/* Defined in `handler.c'. */
|
||||
void read_handler_list (void);
|
||||
void free_handler_list (void);
|
||||
|
||||
/* Defined in `dyncmd.c'. */
|
||||
void read_command_list (const char *prefix);
|
||||
|
||||
/* Defined in `autofs.c'. */
|
||||
void read_fs_list (const char *prefix);
|
||||
|
||||
void grub_context_init (void);
|
||||
void grub_context_fini (void);
|
||||
|
||||
void read_crypto_list (const char *prefix);
|
||||
|
||||
void read_terminal_list (const char *prefix);
|
||||
|
||||
void grub_set_more (int onoff);
|
||||
|
||||
void grub_normal_reset_more (void);
|
||||
|
||||
void grub_xputs_normal (const char *str);
|
||||
|
||||
extern int grub_extractor_level;
|
||||
|
||||
grub_err_t
|
||||
grub_normal_add_menu_entry (int argc, const char **args, char **classes,
|
||||
const char *id,
|
||||
const char *users, const char *hotkey,
|
||||
const char *prefix, const char *sourcecode,
|
||||
int submenu, int *index, struct bls_entry *bls);
|
||||
|
||||
grub_err_t
|
||||
grub_normal_set_password (const char *user, const char *password);
|
||||
|
||||
void grub_normal_free_menu (grub_menu_t menu);
|
||||
|
||||
void grub_normal_auth_init (void);
|
||||
void grub_normal_auth_fini (void);
|
||||
|
||||
void
|
||||
grub_xnputs (const char *str, grub_size_t msg_len);
|
||||
|
||||
grub_command_t
|
||||
grub_dyncmd_get_cmd (grub_command_t cmd);
|
||||
|
||||
void
|
||||
grub_gettext_reread_prefix (const char *val);
|
||||
|
||||
enum grub_human_size_type
|
||||
{
|
||||
GRUB_HUMAN_SIZE_NORMAL,
|
||||
GRUB_HUMAN_SIZE_SHORT,
|
||||
GRUB_HUMAN_SIZE_SPEED,
|
||||
};
|
||||
|
||||
const char *
|
||||
grub_get_human_size (grub_uint64_t size, enum grub_human_size_type type);
|
||||
|
||||
#endif /* ! GRUB_NORMAL_HEADER */
|
@@ -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,14 @@ typedef struct ventoy_img_chunk_list
|
||||
|
||||
#define ventoy_filt_register grub_file_filter_register
|
||||
|
||||
typedef const char * (*grub_env_get_pf)(const char *name);
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
#define GRUB_FILE_REPLACE_MAGIC 0x1258BEEF
|
||||
|
||||
typedef const char * (*grub_env_get_pf)(const char *name);
|
||||
typedef int (*grub_env_set_pf)(const char *name, const char *val);
|
||||
typedef int (*grub_env_printf_pf)(const char *fmt, ...);
|
||||
|
||||
typedef struct ventoy_grub_param_file_replace
|
||||
{
|
||||
grub_uint32_t magic;
|
||||
@@ -217,15 +233,17 @@ typedef struct ventoy_grub_param_file_replace
|
||||
typedef struct ventoy_grub_param
|
||||
{
|
||||
grub_env_get_pf grub_env_get;
|
||||
|
||||
grub_env_set_pf grub_env_set;
|
||||
ventoy_grub_param_file_replace file_replace;
|
||||
grub_env_printf_pf grub_env_printf;
|
||||
}ventoy_grub_param;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
|
||||
|
||||
int grub_ext_get_file_chunk(grub_uint64_t part_start, grub_file_t file, ventoy_img_chunk_list *chunk_list);
|
||||
int grub_fat_get_file_chunk(grub_uint64_t part_start, grub_file_t file, ventoy_img_chunk_list *chunk_list);
|
||||
void grub_iso9660_set_nojoliet(int nojoliet);
|
||||
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
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 newc vga_text ntldr search at_keyboard usb_keyboard gcry_md5 hashsum gzio xzio lzopio lspci pci ext2 xfs ventoy chain read halt iso9660 linux16 test true sleep reboot echo videotest videoinfo videotest_checksum video_colors video_cirrus video_bochs vga vbe video_fb font video gettext extcmd terminal linux minicmd help configfile tr trig boot biosdisk disk ls tar squash4 password_pbkdf2 all_video png jpeg part_gpt part_msdos fat exfat ntfs loopback gzio normal udf gfxmenu gfxterm gfxterm_background gfxterm_menu"
|
||||
|
||||
net_modules_uefi="efinet net tftp http"
|
||||
all_modules_uefi="blocklist ventoy test newc search at_keyboard usb_keyboard gcry_md5 hashsum gzio xzio lzopio ext2 xfs read halt sleep serial terminfo png password_pbkdf2 gcry_sha512 pbkdf2 part_gpt part_msdos ls tar squash4 loopback part_apple minicmd diskfilter linux relocator jpeg iso9660 udf hfsplus halt acpi mmap gfxmenu video_colors trig bitmap_scale gfxterm bitmap font fat exfat ntfs fshelp efifwsetup reboot echo configfile normal terminal gettext chain priority_queue bufio datetime cat extcmd crypto gzio boot all_video efi_gop efi_uga video_bochs video_cirrus video video_fb gfxterm_background gfxterm_menu"
|
||||
|
||||
if [ "$1" = "uefi" ]; then
|
||||
all_modules="$net_modules_uefi $all_modules_uefi "
|
||||
grub-mkimage -v --directory "$VT_DIR/GRUB2/INSTALL/lib/grub/x86_64-efi" --prefix '(,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
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user