mirror of
https://github.com/ventoy/Ventoy.git
synced 2024-12-24 22:25:57 -05:00
commit
458506df75
1
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
1
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1 @@
|
||||
blank_issues_enabled: false
|
93
.github/ISSUE_TEMPLATE/issue_template.yml
vendored
Normal file
93
.github/ISSUE_TEMPLATE/issue_template.yml
vendored
Normal file
@ -0,0 +1,93 @@
|
||||
name: Issue Report
|
||||
description: File an issue report
|
||||
title: "[issue]: "
|
||||
assignees:
|
||||
- octocat
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this issue report!
|
||||
- type: checkboxes
|
||||
id: faq
|
||||
attributes:
|
||||
label: Official FAQ
|
||||
description: Have you checked the official FAQ at [https://www.ventoy.net/en/faq.html](https://www.ventoy.net/en/faq.html) ?
|
||||
options:
|
||||
- label: I have checked the official FAQ.
|
||||
required: true
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: Ventoy Version
|
||||
description: What version of ventoy are you running?
|
||||
placeholder: 1.0.49
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: latestrelease
|
||||
attributes:
|
||||
label: What about latest release
|
||||
description: Have you tried with the latest release of Ventoy?
|
||||
options:
|
||||
- Yes. I have tried the latest release, but the bug still exist.
|
||||
- No. I didn't try the latest release.
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: bios
|
||||
attributes:
|
||||
label: BIOS Mode
|
||||
description: In which BIOS mode did you find the bug?
|
||||
options:
|
||||
- Legacy BIOS Mode
|
||||
- UEFI Mode
|
||||
- Both
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: partstyle
|
||||
attributes:
|
||||
label: Partition Style
|
||||
description: Which partition style did you select when you install Ventoy?
|
||||
options:
|
||||
- MBR
|
||||
- GPT
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: capacity
|
||||
attributes:
|
||||
label: Disk Capacity
|
||||
description: What is the capacity of the disk installed with Ventoy?
|
||||
placeholder: 32GB
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: checksum
|
||||
attributes:
|
||||
label: Image file checksum (if applicable)
|
||||
description: Have you checked the image file in Ventoy's menu as [https://www.ventoy.net/en/faq.html#faq_boot_checksum](https://www.ventoy.net/en/faq.html#faq_boot_checksum) ?
|
||||
options:
|
||||
- Yes.
|
||||
- No.
|
||||
validations:
|
||||
required: false
|
||||
- type: input
|
||||
id: link
|
||||
attributes:
|
||||
label: Image file download link (if applicable)
|
||||
description: What is the image file download link?
|
||||
placeholder: https://xxx
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: what-happened
|
||||
attributes:
|
||||
label: What happened?
|
||||
description: Tell me what happened. It's highly recommended to include some photo or video about the bug.
|
||||
placeholder: Tell us what you see!
|
||||
value: "A bug happened!"
|
||||
validations:
|
||||
required: true
|
||||
|
33
.github/workflows/ci.yml
vendored
Normal file
33
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
name: Ventoy CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
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-windows
|
||||
path: INSTALL/ventoy-*windows*
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ventoy-linux
|
||||
path: INSTALL/ventoy-*linux*
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ventoy-livecd
|
||||
path: INSTALL/ventoy-*livecd*
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: xxx-build-log
|
||||
path: DOC/build.log
|
25
.github/workflows/sync2gitee.yml
vendored
Normal file
25
.github/workflows/sync2gitee.yml
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
name: Mirror GitHub to Gitee
|
||||
|
||||
on:
|
||||
# Triggers the workflow on push or pull request events but only for the main branch
|
||||
push:
|
||||
branches: [ master ]
|
||||
|
||||
# Allows you to run this workflow manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
run:
|
||||
name: Sync-GitHub-to-Gitee
|
||||
if: ${{ github.repository_owner == 'ventoy' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Mirror the Github repos to Gitee.
|
||||
uses: Yikun/hub-mirror-action@master
|
||||
with:
|
||||
src: github/ventoy
|
||||
dst: gitee/LongPanda
|
||||
dst_key: ${{ secrets.GITEE_PRIVATE_KEY }}
|
||||
dst_token: ${{ secrets.GITEE_TOKEN }}
|
||||
static_list: "Ventoy"
|
||||
force_update: true
|
1166
BUSYBOX/aarch64_ash.config
Normal file
1166
BUSYBOX/aarch64_ash.config
Normal file
File diff suppressed because it is too large
Load Diff
1166
BUSYBOX/aarch64_hexdump.config
Normal file
1166
BUSYBOX/aarch64_hexdump.config
Normal file
File diff suppressed because it is too large
Load Diff
1166
BUSYBOX/aarch64_xzcat.config
Normal file
1166
BUSYBOX/aarch64_xzcat.config
Normal file
File diff suppressed because it is too large
Load Diff
55
BUSYBOX/build.txt
Normal file
55
BUSYBOX/build.txt
Normal file
@ -0,0 +1,55 @@
|
||||
======== How to build ash/hexdump/xzcat for aarch64 ========
|
||||
#How to get ash.config/hexdump.cofig/xzcat.config
|
||||
#ARCH=arm64 CROSS_COMPILE=aarch64-linux- make allnoconfig
|
||||
#ARCH=arm64 CROSS_COMPILE=aarch64-linux- make menuconfig
|
||||
#----> enable static build
|
||||
#----> enable xzcat
|
||||
#get aarch64_xzcat.config
|
||||
|
||||
tar xf busybox-1.32.0.tar.bz2
|
||||
cd busybox-1.32.0
|
||||
copy aarch64_xzcat.config as .config
|
||||
ARCH=arm64 CROSS_COMPILE=aarch64-linux- make
|
||||
rename ./busybox to xzcat
|
||||
|
||||
|
||||
======== How to build ash/hexdump/xzcat for mips64el ========
|
||||
#download mips64el-musl cross toolchain from https://github.com/ventoy/musl-cross-make/releases/download/latest/
|
||||
#How to get ash.config/hexdump.cofig/xzcat.config
|
||||
#ARCH=mips CROSS_COMPILE=mips64el-linux-musl- make allnoconfig "CFLAGS+=-mips64r2 -mabi=64 -Os" "LDFLAGS+=-mips64r2 -mabi=64 -Os"
|
||||
#ARCH=mips CROSS_COMPILE=mips64el-linux-musl- make menuconfig "CFLAGS+=-mips64r2 -mabi=64 -Os" "LDFLAGS+=-mips64r2 -mabi=64 -Os"
|
||||
#----> enable static build
|
||||
#----> enable xzcat
|
||||
#get mips64el_xzcat.config
|
||||
|
||||
tar xf busybox-1.32.0.tar.bz2
|
||||
cd busybox-1.32.0
|
||||
copy mips64el_xzcat.config as .config
|
||||
ARCH=mips CROSS_COMPILE=mips64el-linux-musl- make "CFLAGS+=-mips64r2 -mabi=64 -Os" "LDFLAGS+=-mips64r2 -mabi=64 -Os"
|
||||
rename ./busybox to xzcat
|
||||
|
||||
|
||||
======== How to build full busybox =========
|
||||
#make defconfig
|
||||
#make menuconfig select static build
|
||||
|
||||
======== How to build ash/hexdump/xzcat for x86_64 ==========
|
||||
#How to get ash.config/hexdump.cofig/xzcat.config
|
||||
#make allnoconfig
|
||||
#make menuconfig
|
||||
#----> enable static build
|
||||
#----> enable xzcat
|
||||
#get x86_64_xzcat.config
|
||||
|
||||
|
||||
tar xf busybox-1.32.0.tar.bz2
|
||||
cd busybox-1.32.0
|
||||
copy x86_64_xzcat.config as .config
|
||||
modify Makefile
|
||||
CC = gcc -specs "/usr/local/musl/lib/musl-gcc.specs"
|
||||
MODFLAGS = -DMODULE -specs "/usr/local/musl/lib/musl-gcc.specs"
|
||||
make
|
||||
rename ./busybox to xzcat
|
||||
|
||||
|
||||
|
31
BUSYBOX/chmod/build.sh
Normal file
31
BUSYBOX/chmod/build.sh
Normal file
@ -0,0 +1,31 @@
|
||||
#!/bin/sh
|
||||
|
||||
DSTDIR=../../IMG/cpio/ventoy/busybox
|
||||
|
||||
rm -f vtchmod32 vtchmod64 vtchmod64_musl vtchmodaa64
|
||||
rm -f $DSTDIR/vtchmod32 $DSTDIR/vtchmod64 $DSTDIR/vtchmodaa64 $DSTDIR/vtchmodm64e
|
||||
|
||||
/opt/diet32/bin/diet gcc -Os -m32 vtchmod.c -o vtchmod32
|
||||
/opt/diet64/bin/diet gcc -Os vtchmod.c -o vtchmod64
|
||||
aarch64-linux-gcc -Os -static vtchmod.c -o vtchmodaa64
|
||||
aarch64-linux-strip --strip-all vtchmodaa64
|
||||
|
||||
mips64el-linux-musl-gcc -mips64r2 -mabi=64 -Os -static vtchmod.c -o vtchmodm64e
|
||||
mips64el-linux-musl-strip --strip-all vtchmodm64e
|
||||
|
||||
|
||||
gcc -specs "/usr/local/musl/lib/musl-gcc.specs" -Os -static vtchmod.c -o vtchmod64_musl
|
||||
strip --strip-all vtchmod64_musl
|
||||
|
||||
chmod 777 vtchmod32
|
||||
chmod 777 vtchmod64
|
||||
chmod 777 vtchmodaa64
|
||||
chmod 777 vtchmod64_musl
|
||||
chmod 777 vtchmodm64e
|
||||
|
||||
cp -a vtchmod32 $DSTDIR/
|
||||
cp -a vtchmod64 $DSTDIR/
|
||||
cp -a vtchmodaa64 $DSTDIR/
|
||||
cp -a vtchmod64_musl $DSTDIR/
|
||||
cp -a vtchmodm64e $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.
BIN
BUSYBOX/chmod/vtchmod64_musl
Normal file
BIN
BUSYBOX/chmod/vtchmod64_musl
Normal file
Binary file not shown.
BIN
BUSYBOX/chmod/vtchmodaa64
Normal file
BIN
BUSYBOX/chmod/vtchmodaa64
Normal file
Binary file not shown.
BIN
BUSYBOX/chmod/vtchmodm64e
Normal file
BIN
BUSYBOX/chmod/vtchmodm64e
Normal file
Binary file not shown.
1181
BUSYBOX/config
Normal file
1181
BUSYBOX/config
Normal file
File diff suppressed because it is too large
Load Diff
1166
BUSYBOX/mips64el_ash.config
Normal file
1166
BUSYBOX/mips64el_ash.config
Normal file
File diff suppressed because it is too large
Load Diff
1166
BUSYBOX/mips64el_hexdump.config
Normal file
1166
BUSYBOX/mips64el_hexdump.config
Normal file
File diff suppressed because it is too large
Load Diff
1166
BUSYBOX/mips64el_xzcat.config
Normal file
1166
BUSYBOX/mips64el_xzcat.config
Normal file
File diff suppressed because it is too large
Load Diff
1166
BUSYBOX/x86_64_ash.config
Normal file
1166
BUSYBOX/x86_64_ash.config
Normal file
File diff suppressed because it is too large
Load Diff
1166
BUSYBOX/x86_64_hexdump.config
Normal file
1166
BUSYBOX/x86_64_hexdump.config
Normal file
File diff suppressed because it is too large
Load Diff
1166
BUSYBOX/x86_64_xzcat.config
Normal file
1166
BUSYBOX/x86_64_xzcat.config
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,31 +1,70 @@
|
||||
Build a static linked, small dmsetup tool
|
||||
|
||||
======== Source Code ========
|
||||
use an old version of dmsetup
|
||||
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
|
||||
1. install centos 6.10 i386 with CentOS-6.10-i386-bin-DVD1.iso
|
||||
2. yum install gcc kernel-devel package
|
||||
3. install dietc libc (just make && make install)
|
||||
4. export PATH=$PATH:/opt/diet/bin
|
||||
|
||||
======== Build Step ========
|
||||
1. extract device mapper source code
|
||||
2. CC="diet gcc" ./configure --disable-nls --disable-selinux --disable-shared
|
||||
3. modify include/configure.h file
|
||||
--- delete the line with "#define malloc rpl_malloc"
|
||||
--- add 2 defines as follow:
|
||||
#ifndef UINT32_MAX
|
||||
#define UINT32_MAX (4294967295U)
|
||||
#endif
|
||||
|
||||
#ifndef UINT64_C
|
||||
#define UINT64_C(c) c ## ULL
|
||||
#endif
|
||||
|
||||
4. make
|
||||
5. strip dmsetup/dmsetup
|
||||
5. get dmsetup/dmsetup as the binary file
|
||||
Build a static linked, small dmsetup tool
|
||||
|
||||
======== Source Code ========
|
||||
use an old version of dmsetup
|
||||
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
|
||||
1. install centos 6.10 i386 with CentOS-6.10-i386-bin-DVD1.iso
|
||||
2. yum install gcc kernel-devel package
|
||||
3. install dietc libc (just make && make install)
|
||||
4. export PATH=$PATH:/opt/diet/bin
|
||||
|
||||
======== Build Step ========
|
||||
1. extract device mapper source code
|
||||
2. CC="diet gcc" ./configure --disable-nls --disable-selinux --disable-shared
|
||||
3. modify include/configure.h file
|
||||
--- delete the line with "#define malloc rpl_malloc"
|
||||
--- add 2 defines as follow:
|
||||
#ifndef UINT32_MAX
|
||||
#define UINT32_MAX (4294967295U)
|
||||
#endif
|
||||
|
||||
#ifndef UINT64_C
|
||||
#define UINT64_C(c) c ## ULL
|
||||
#endif
|
||||
|
||||
4. make
|
||||
5. strip dmsetup/dmsetup
|
||||
6. get dmsetup/dmsetup as the dmsetup32 binary file
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
======================== Build for 64bit dmsetup =========================
|
||||
1. extract device mapper source code
|
||||
2. ./configure --disable-nls --disable-selinux --disable-shared --enable-static_link CC='gcc -specs /usr/local/musl/lib/musl-gcc.specs'
|
||||
3. touch include/linux/limits.h include/linux/types.h
|
||||
echo '#include <sys/mount.h>' > include/linux/fs.h
|
||||
4. make
|
||||
5. strip --strip-all dmsetup/dmsetup.static
|
||||
6. get dmsetup/dmsetup.static as the dmsetup64 binary file
|
||||
|
||||
|
||||
======================== Build for arm64 dmsetup =========================
|
||||
1. extract device mapper source code
|
||||
2. ./configure CC=aarch64-linux-gcc --target=arm --host=x86_64-linux-gnu --disable-nls --disable-selinux --disable-shared --enable-static_link
|
||||
3. modify include/configure.h file
|
||||
--- delete the line with "#define malloc rpl_malloc"
|
||||
4. make
|
||||
5. aarch64-linux-strip dmsetup/dmsetup.static
|
||||
6. get dmsetup/dmsetup.static as the dmsetupaa64 binary file
|
||||
|
||||
|
||||
======================== Build for mips64 dmsetup =========================
|
||||
1. extract device mapper source code
|
||||
2. ./configure CC="mips64el-linux-musl-gcc -mips64r2 -mabi=64" --target=mips --host=x86_64-linux-gnu --disable-nls --disable-selinux --disable-shared --enable-static_link
|
||||
3. modify include/configure.h file
|
||||
--- delete the line with "#define malloc rpl_malloc"
|
||||
4. make
|
||||
5. mips64el-linux-musl-strip dmsetup/dmsetup.static
|
||||
6. get dmsetup/dmsetup.static as the dmsetupm64e binary file
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
BIN
DMSETUP/dmsetup64
Normal file
BIN
DMSETUP/dmsetup64
Normal file
Binary file not shown.
BIN
DMSETUP/dmsetupaa64
Normal file
BIN
DMSETUP/dmsetupaa64
Normal file
Binary file not shown.
BIN
DMSETUP/dmsetupm64e
Normal file
BIN
DMSETUP/dmsetupm64e
Normal file
Binary file not shown.
@ -1,204 +1,260 @@
|
||||
|
||||
==========================================
|
||||
1. Compile Enviroment
|
||||
==========================================
|
||||
My build envrioment is CentOS 7.8 x86_64. So here I first explain how to create the build environment from scratch.
|
||||
Because Ventoy is based on many open source projects, so the envrioment is important. I suggest you test it on a virtual machine first.
|
||||
|
||||
1.1 Install CentOS 7.8
|
||||
I use CentOS-7-x86_64-Everything-2003.iso and select Minimal install
|
||||
|
||||
1.2 Install Packages
|
||||
yum install \
|
||||
libXpm net-tools bzip2 wget vim gcc gcc-c++ samba dos2unix glibc-devel glibc.i686 glibc-devel.i686 \
|
||||
mpfr.i686 mpfr-devel.i686 zlib.i686 rsync autogen autoconf automake libtool gettext* bison binutils \
|
||||
flex device-mapper-devel SDL libpciaccess libusb freetype freetype-devel gnu-free-* qemu-* virt-* \
|
||||
libvirt* vte* NetworkManager-bluetooth brlapi fuse-devel dejavu* gnu-efi* pesign shim \
|
||||
iscsi-initiator-utils grub2-tools zip nasm acpica-tools glibc-static zlib-static
|
||||
|
||||
|
||||
|
||||
==========================================
|
||||
2. Download Source Code
|
||||
==========================================
|
||||
2.1 Download Ventoy source code from github and decompress it.
|
||||
Next I assume that you have unzipped the code into the /home directory (check /home/Ventoy-master/README.md file for the directory level).
|
||||
|
||||
2.2 Download third-part source code
|
||||
|
||||
https://www.fefe.de/dietlibc/dietlibc-0.34.tar.xz ===> /home/Ventoy-master/DOC/dietlibc-0.34.tar.xz
|
||||
https://ftp.gnu.org/gnu/grub/grub-2.04.tar.xz ===> /home/Ventoy-master/GRUB2/grub-2.04.tar.xz
|
||||
https://codeload.github.com/tianocore/edk2/zip/edk2-stable201911 ===> /home/Ventoy-master/EDK2/edk2-edk2-stable201911.zip
|
||||
https://codeload.github.com/relan/exfat/zip/v1.3.0 ===> /home/Ventoy-master/ExFAT/exfat-1.3.0.zip
|
||||
https://codeload.github.com/libfuse/libfuse/zip/fuse-2.9.9 ===> /home/Ventoy-master/ExFAT/libfuse-fuse-2.9.9.zip
|
||||
|
||||
|
||||
|
||||
==========================================
|
||||
3. All in one script
|
||||
==========================================
|
||||
I have made the whole build process in all_in_one.sh, you can run this script to build and pack ventoy.
|
||||
If you want to compile a certain part separately, you can continue to refer to the later chapters of this text.
|
||||
|
||||
cd /home/Ventoy-master/INSTALL
|
||||
sh all_in_one.sh
|
||||
|
||||
It should be noted that, some part of Ventoy has 32bit&64bit version (like 4.9 4.10 4.11 follows)
|
||||
all_in_one.sh only build 64bit version of them, if you want to rebuild the 32bit verison. You should create a 32bit CentOS environment and build them.
|
||||
Fortunately these parts are few modified, you only need to build once or you can directly use the binary I have built.
|
||||
|
||||
Besides, after a fully compile and pack, you can only build the part you modified (for example grub2) and run ventoy_pack.sh to generate the package.
|
||||
|
||||
|
||||
|
||||
==========================================
|
||||
4. Build every part of Ventoy
|
||||
==========================================
|
||||
4.1 == Build grub2 ==
|
||||
cd /home/Ventoy-master/GRUB2
|
||||
sh buildgrub.sh
|
||||
|
||||
4.2 == Build ipxe.krn ==
|
||||
cd /home/Ventoy-master/IPXE
|
||||
sh buildipxe.sh
|
||||
|
||||
4.3 == Build Ventoy2Disk.exe ==
|
||||
Ventoy2Disk.exe is the installer in Windows platform. And it must be built in Windows with Microsoft Visual Studio (2013+).
|
||||
Open /home/Ventoy-master/Ventoy2Disk/Ventoy2Disk.sln with Visual Studio and build it.
|
||||
|
||||
4.4 == Build vtoyjump64.exe/vtoyjump32.exe ==
|
||||
vtoyjump64.exe/vtoyjump32.exe is used to mount iso file in windows PE. You should install Microsoft Visual Studio (2013+) to build it.
|
||||
Open /home/Ventoy-master/vtoyjump/vtoyjump.sln with Visual Studio and build it (64&32).
|
||||
|
||||
4.5 == Build dmsetup ==
|
||||
Please refer to DMSETUP/build.txt
|
||||
|
||||
4.6 == Build ventoy_x64.efi ==
|
||||
cd /home/Ventoy-master/EDK2
|
||||
sh buildedk.sh
|
||||
|
||||
4.7 == Build VtoyTool ==
|
||||
cd /home/Ventoy-master/VtoyTool
|
||||
sh build.sh
|
||||
|
||||
4.8 == Build vtoyfat ==
|
||||
cd /home/Ventoy-master/vtoyfat/fat_io_lib
|
||||
sh buildlib.sh
|
||||
cd /home/Ventoy-master/vtoyfat
|
||||
sh build.sh
|
||||
|
||||
4.9 == Build exfat-util ==
|
||||
cd /home/Ventoy-master/ExFAT
|
||||
sh buidlibfuse.sh
|
||||
sh buidexfat.sh
|
||||
|
||||
After that, copy EXFAT/shared/mkexfatfs ===> /home/Ventoy-master/INSTALL/tool/mkexfatfs_64
|
||||
After that, copy EXFAT/shared/mount.exfat-fuse ===> /home/Ventoy-master/INSTALL/tool/mount.exfat-fuse_64
|
||||
|
||||
Use the same build step to build exfat-util 32bit in a 32bit CentOS system and get mkexfatfs_32 and mount.exfat-fuse_32
|
||||
|
||||
4.10 == Build vtoy_fuse_iso_64/vtoy_fuse_iso_32 ==
|
||||
cd /home/Ventoy-master/FUSEISO
|
||||
sh build_libfuse.sh
|
||||
sh build.sh
|
||||
|
||||
Use the same build step to build in a 32bit CentOS system and get vtoy_fuse_iso_32
|
||||
|
||||
4.11 == Build unsquashfs_64/unsquashfs_32 ==
|
||||
cd /home/Ventoy-master/SQUASHFS/SRC
|
||||
sh build_lz4.sh
|
||||
sh build_lzma.sh
|
||||
sh build_lzo.sh
|
||||
sh build_zstd.sh
|
||||
|
||||
cd /home/Ventoy-master/SQUASHFS/squashfs-tools-4.4/squashfs-tools
|
||||
sh build.sh
|
||||
|
||||
Use the same build step to build in a 32bit CentOS system and get unsquashfs_32
|
||||
|
||||
4.12 == Build vblade_64/vblade_32 ==
|
||||
cd /home/Ventoy-master/VBLADE/vblade-master
|
||||
sh build.sh
|
||||
|
||||
4.13 == Build zstdcat ==
|
||||
Please refer to ZSTD/build.txt
|
||||
|
||||
4.14 == Build vtoy_gen_uuid ==
|
||||
cd /home/Ventoy-master/GenUUID
|
||||
sh build.sh
|
||||
|
||||
4.15 == Build xzminidec ==
|
||||
cd /home/Ventoy-master/xz-embedded-20130513/userspace
|
||||
make -f ventoy_makefile
|
||||
strip --strip-all xzminidec
|
||||
|
||||
4.16 == Build iso9660_x64.efi ==
|
||||
This efi driver is from https://github.com/pbatard/efifs
|
||||
Follow all the build instructions in this project. I modified 3 files (the original and modified source are at /home/Ventoy-master/EDK2/efiffs)
|
||||
|
||||
|
||||
|
||||
==========================================
|
||||
5. Binaries
|
||||
==========================================
|
||||
There some binaries in Ventoy install package. These files are downloaded from other open source project's website, such as busybox.
|
||||
Here is the list of the binaries, their SHA-256 and the download urls:
|
||||
|
||||
5.1 IMG/cpio/ventoy/tool/lz4cat
|
||||
https://create.stephan-brumme.com/smallz4 smallz4cat-x32-v1.4
|
||||
SHA-256: 13d293ddeedb469f51da41167f79b2cbdb904e681716f6e6191b233dbb162438
|
||||
|
||||
5.2 IMG/cpio/ventoy/tool/ar
|
||||
https://busybox.net/downloads/binaries/1.30.0-i686 busybox_AR
|
||||
SHA-256: f29b7d81a983c0c85d22496f4a833c18f2528a1b666eb7d47c93084c1ed66ae0
|
||||
|
||||
5.3 IMG/cpio/ventoy/tool/inotifyd
|
||||
https://busybox.net/downloads/binaries/1.30.0-i686 busybox_INOTIFYD
|
||||
SHA-256: 3532162a8695e91a1ed9ddea28b2cb22259a90e93d5d9c4a517b6c36842c686f
|
||||
|
||||
5.4 IMG/cpio/ventoy/busybox/tmpsh
|
||||
https://busybox.net/downloads/binaries/1.27.1-i686 busybox_ASH
|
||||
SHA-256: 44a6274bca580c2758ffc173fc76d18bb855b1fe8dcf70efd9ee75cbd57dee97
|
||||
|
||||
5.5 IMG/cpio/ventoy/busybox/tmpxz
|
||||
https://busybox.net/downloads/binaries/1.27.1-i686 busybox_XZ
|
||||
SHA-256: f6cdb6293680424c29b89bde0685ca27f455166c9b302cd6082ef90681456291
|
||||
|
||||
5.6 INSTALL/tool/xzcat
|
||||
https://busybox.net/downloads/binaries/1.30.0-i686/ busybox_XZCAT
|
||||
SHA-256: 7399db642c2beaf52a16ab5264ffc55cfd1ff5699a524f63e5d48edf84e20f44
|
||||
|
||||
5.7 INSTALL/tool/hexdump
|
||||
https://busybox.net/downloads/binaries/1.30.0-i686/ busybox_HEXDUMP
|
||||
SHA-256: cde08b6a2cf5ad914f05203e18e3f7c2ed6060a63604e3d75536f19b55e8e0af
|
||||
|
||||
5.8 imdisk
|
||||
download http://www.ltr-data.se/files/imdiskinst.exe and extract it by 7zip.
|
||||
|
||||
INSTALL/ventoy/imdisk/64/imdisk.sys --> sys/amd64/imdisk.sys SHA-256: 6702202220268787e361f5a82dae53362c8e6c6dcd240bb01b44dd77ae0788da
|
||||
INSTALL/ventoy/imdisk/64/imdisk.exe --> cli/amd64/imdisk.exe SHA-256: 9759175380af836869443e5f21ce2e33022125d154bc6b3d1c04dc36b190de04
|
||||
INSTALL/ventoy/imdisk/64/imdisk.cpl --> cpl/amd64/imdisk.cpl SHA-256: aea2ebbea2b073c947263744962af8a3eab025ff4c9d825c543e380e738a4c99
|
||||
|
||||
INSTALL/ventoy/imdisk/32/imdisk.sys --> sys/i386/imdisk.sys SHA-256: a94caec2f71a924d6a914c093ad4b905d7cfdea3f515ed48aaa8c3950b2dc191
|
||||
INSTALL/ventoy/imdisk/32/imdisk.exe --> cli/i386/imdisk.exe SHA-256: 33b53858e2139704cf603b115a3e5e1dfd4daeaaed4d3e03c633f2df3b55dbaa
|
||||
INSTALL/ventoy/imdisk/32/imdisk.cpl --> cpl/i386/imdisk.cpl SHA-256: b781d3e2d286ac8bf548f44e50cbbb3fe78203296e41e4d2e73b407668f88f2d
|
||||
|
||||
5.9 INSTALL/ventoy/memdisk
|
||||
https://mirrors.edge.kernel.org/pub/linux/utils/boot/syslinux/syslinux-6.03.tar.gz
|
||||
decompress it and memdisk is at syslinux-6.03/bios/memdisk/memdisk
|
||||
SHA-256: 3f6cd656b8a14109cd3f906fee2dd2e75418f983a5e1bfdb64f44f7765588cbb
|
||||
|
||||
|
||||
5.10 UEFIinSecureBoot
|
||||
https://github.com/ValdikSS/Super-UEFIinSecureBoot-Disk/releases Super-UEFIinSecureBoot-Disk_minimal_v3.zip
|
||||
unzip it and get Super-UEFIinSecureBoot-Disk_minimal.img, extract the img by 7zip.
|
||||
|
||||
INSTALL/EFI/BOOT/BOOTX64.EFI --> EFI/BOOT/BOOTX64.EFI SHA-256: 475552c7476ad45e42344eee8b30d44c264d200ac2468428aa86fc8795fb6e34
|
||||
INSTALL/EFI/BOOT/grubx64.efi --> EFI/BOOT/grubx64.efi SHA-256: 25d858157349dc52fa70f3cdf5c62fe1e0bae37ddfc3a6b6528af9a3c745775f
|
||||
INSTALL/EFI/BOOT/MokManager.efi --> EFI/BOOT/MokManager.efi SHA-256: 3bf1f46cee0832355c7dd1dba880dea9bcaa78cc44375a1559d43bc9db18933b
|
||||
|
||||
|
||||
5.11 INSTALL/tool/ash
|
||||
https://busybox.net/downloads/binaries/1.31.0-i686-uclibc/ busybox_ASH
|
||||
SHA-256: 2943f02f85fee0c9551aec47110a558a73f919c032b3c51e56d6f197b5ec4d7b
|
||||
|
||||
|
||||
==========================================
|
||||
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 environment is important. I suggest you test it on a virtual machine firstly.
|
||||
|
||||
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 xorriso
|
||||
|
||||
|
||||
|
||||
==========================================
|
||||
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 layout).
|
||||
|
||||
2.2 Download third-part source code and tool
|
||||
|
||||
https://www.fefe.de/dietlibc/dietlibc-0.34.tar.xz ===> /home/Ventoy-master/DOC/dietlibc-0.34.tar.xz
|
||||
https://musl.libc.org/releases/musl-1.2.1.tar.gz ===> /home/Ventoy-master/DOC/musl-1.2.1.tar.gz
|
||||
https://ftp.gnu.org/gnu/grub/grub-2.04.tar.xz ===> /home/Ventoy-master/GRUB2/grub-2.04.tar.xz
|
||||
https://codeload.github.com/tianocore/edk2/zip/edk2-stable201911 ===> /home/Ventoy-master/EDK2/edk2-edk2-stable201911.zip
|
||||
https://codeload.github.com/relan/exfat/zip/v1.3.0 ===> /home/Ventoy-master/ExFAT/exfat-1.3.0.zip
|
||||
https://codeload.github.com/libfuse/libfuse/zip/fuse-2.9.9 ===> /home/Ventoy-master/ExFAT/libfuse-fuse-2.9.9.zip
|
||||
https://releases.linaro.org/components/toolchain/binaries/7.4-2019.02/aarch64-linux-gnu/gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu.tar.xz ===> /opt/gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu.tar.xz
|
||||
https://toolchains.bootlin.com/downloads/releases/toolchains/aarch64/tarballs/aarch64--uclibc--stable-2020.08-1.tar.bz2 ===> /opt/aarch64--uclibc--stable-2020.08-1.tar.bz2
|
||||
http://ftp.loongnix.org/toolchain/gcc/release/mips-loongson-gcc7.3-2019.06-29-linux-gnu.tar.gz ===> /opt/mips-loongson-gcc7.3-2019.06-29-linux-gnu.tar.gz
|
||||
https://github.com/ventoy/musl-cross-make/releases/download/latest/output.tar.bz2 ===> /opt/output.tar.bz2
|
||||
|
||||
|
||||
http://www.tinycorelinux.net/11.x/x86_64/release/distribution_files/vmlinuz64 ===> /home/Ventoy-master/LiveCD/ISO/EFI/boot/vmlinuz64
|
||||
http://www.tinycorelinux.net/11.x/x86_64/release/distribution_files/corepure64.gz ===> /home/Ventoy-master/LiveCD/ISO/EFI/boot/corepure64.gz
|
||||
http://www.tinycorelinux.net/11.x/x86_64/release/distribution_files/modules64.gz ===> /home/Ventoy-master/LiveCD/ISO/EFI/boot/modules64.gz
|
||||
|
||||
2.3 Prepare third-part tools
|
||||
cd /home/Ventoy-master/DOC/
|
||||
tar xf musl-1.2.1.tar.gz
|
||||
cd musl-1.2.1
|
||||
./configure && make install
|
||||
|
||||
tar xf /opt/gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu.tar.xz -C /opt
|
||||
tar xf /opt/aarch64--uclibc--stable-2020.08-1.tar.bz2 -C /opt
|
||||
tar xf /opt/output.tar.bz2 -C /opt
|
||||
mv /opt/output /opt/mips64el-linux-musl-gcc730
|
||||
|
||||
|
||||
2.4 Set PATH envrioment
|
||||
export PATH=$PATH:/opt/gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu/bin:/opt/aarch64--uclibc--stable-2020.08-1/bin:/opt/mips64el-linux-musl-gcc730/bin
|
||||
better to add this line to /root/.bashrc and relogin as root
|
||||
|
||||
|
||||
==========================================
|
||||
3. All in one script
|
||||
==========================================
|
||||
I have made a 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:
|
||||
1. Only grub2/EDK2/IPXE will be recompiled in all_in_one.sh. Other part contains the binaries and are few modified, so will no be recompiled everytime.
|
||||
You can rebuild these parts separately if you want.
|
||||
|
||||
2. 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/x86_64_ash.config and uclibc to build busybox-1.32
|
||||
|
||||
4.19 == Build lunzip32/lunzip64 ==
|
||||
http://mirror.yongbok.net/nongnu/lzip/lunzip/lunzip-1.11.tar.gz
|
||||
PATH=$PATH:/opt/diet/bin
|
||||
./configure --disable-nls CC='diet gcc -nostdinc'
|
||||
make
|
||||
strip --strip-all lunzip
|
||||
|
||||
#aarch64
|
||||
./configure --disable-nls CC='aarch64-buildroot-linux-uclibc-gcc -static'
|
||||
make
|
||||
aarch64-buildroot-linux-uclibc-strip --strip-all lunzip
|
||||
|
||||
|
||||
|
||||
==========================================
|
||||
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/i386/xzcat
|
||||
https://busybox.net/downloads/binaries/1.30.0-i686/ busybox_XZCAT
|
||||
SHA-256: 7399db642c2beaf52a16ab5264ffc55cfd1ff5699a524f63e5d48edf84e20f44
|
||||
|
||||
5.7 INSTALL/tool/i386/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
|
||||
|
||||
|
||||
|
9
DOC/prepare_env.sh
Normal file
9
DOC/prepare_env.sh
Normal file
@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
#[ -d /opt/diet64 ] || sh ./installdietlibc.sh
|
||||
|
||||
[ -d /opt/gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu ] || tar xf /opt/gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu.tar.xz -C /opt
|
||||
|
||||
[ -d /opt/aarch64--uclibc--stable-2020.08-1 ] || tar xf /opt/aarch64--uclibc--stable-2020.08-1.tar.bz2 -C /opt
|
||||
|
||||
[ -d /opt/mips-loongson-gcc7.3-linux-gnu ] || tar xf /opt/mips-loongson-gcc7.3-2019.06-29-linux-gnu.tar.gz -C /opt
|
15
Dockerfile
15
Dockerfile
@ -1,17 +1,10 @@
|
||||
FROM centos:7
|
||||
|
||||
RUN yum -y install \
|
||||
RUN yum -y -q 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 \
|
||||
mpfr.i686 mpfr-devel.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
|
||||
iscsi-initiator-utils grub2-tools zip nasm acpica-tools glibc-static zlib-static xorriso
|
||||
|
||||
CMD cd /ventoy/INSTALL && ls -la && sh docker_ci_build.sh
|
||||
|
59
EDK2/build.sh
Normal file
59
EDK2/build.sh
Normal file
@ -0,0 +1,59 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
EDKARCH=X64
|
||||
postfix=x64
|
||||
elif [ "$1" = "ia32" ]; then
|
||||
EDKARCH=IA32
|
||||
postfix=ia32
|
||||
shift
|
||||
elif [ "$1" = "aa64" ]; then
|
||||
EDKARCH=AARCH64
|
||||
postfix=aa64
|
||||
shift
|
||||
fi
|
||||
|
||||
cd edk2-edk2-stable201911
|
||||
|
||||
rm -rf ./Conf/.cache
|
||||
rm -f ./Conf/.AutoGenIdFile.txt
|
||||
|
||||
VTEFI_PATH=Build/MdeModule/RELEASE_GCC48/$EDKARCH/MdeModulePkg/Application/Ventoy/Ventoy/OUTPUT/Ventoy.efi
|
||||
DST_PATH=../../INSTALL/ventoy/ventoy_${postfix}.efi
|
||||
|
||||
VTEFI_PATH2=Build/MdeModule/RELEASE_GCC48/$EDKARCH/MdeModulePkg/Application/VtoyUtil/VtoyUtil/OUTPUT/VtoyUtil.efi
|
||||
DST_PATH2=../../INSTALL/ventoy/vtoyutil_${postfix}.efi
|
||||
|
||||
VTEFI_PATH3=Build/MdeModule/RELEASE_GCC48/$EDKARCH/MdeModulePkg/Application/VDiskChain/VDiskChain/OUTPUT/VDiskChain.efi
|
||||
DST_PATH3=../../VDiskChain/Tool/vdiskchain_${postfix}.efi
|
||||
|
||||
|
||||
rm -f $VTEFI_PATH
|
||||
rm -f $DST_PATH
|
||||
rm -f $VTEFI_PATH2
|
||||
rm -f $DST_PATH2
|
||||
rm -f $VTEFI_PATH3
|
||||
[ -d ../../VDiskChain ] && rm -f $DST_PATH3
|
||||
|
||||
unset WORKSPACE
|
||||
source ./edksetup.sh
|
||||
|
||||
if [ "$EDKARCH" = "AARCH64" ]; then
|
||||
GCC48_AARCH64_PREFIX=aarch64-linux-gnu- \
|
||||
build -p MdeModulePkg/MdeModulePkg.dsc -a $EDKARCH -b RELEASE -t GCC48
|
||||
else
|
||||
build -p MdeModulePkg/MdeModulePkg.dsc -a $EDKARCH -b RELEASE -t GCC48
|
||||
fi
|
||||
|
||||
if [ -e $VTEFI_PATH ] && [ -e $VTEFI_PATH2 ] && [ -e $VTEFI_PATH3 ]; then
|
||||
echo -e '\n\n====================== SUCCESS ========================\n\n'
|
||||
cp -a $VTEFI_PATH $DST_PATH
|
||||
cp -a $VTEFI_PATH2 $DST_PATH2
|
||||
[ -d ../../VDiskChain ] && cp -a $VTEFI_PATH3 $DST_PATH3
|
||||
cd ..
|
||||
else
|
||||
echo -e '\n\n====================== FAILED ========================\n\n'
|
||||
cd ..
|
||||
exit 1
|
||||
fi
|
||||
|
@ -2,32 +2,20 @@
|
||||
|
||||
rm -rf edk2-edk2-stable201911
|
||||
|
||||
unzip edk2-edk2-stable201911.zip
|
||||
unzip edk2-edk2-stable201911.zip > /dev/null
|
||||
|
||||
/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/
|
||||
cd ..
|
||||
|
||||
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
|
||||
echo '======== build EDK2 for i386-efi ==============='
|
||||
sh ./build.sh ia32 || exit 1
|
||||
|
||||
echo '======== build EDK2 for arm64-efi ==============='
|
||||
sh ./build.sh aa64 || exit 1
|
||||
|
||||
echo '======== build EDK2 for x86_64-efi ==============='
|
||||
sh ./build.sh || exit 1
|
||||
|
||||
|
@ -0,0 +1,466 @@
|
||||
/******************************************************************************
|
||||
* VDiskChain.c
|
||||
*
|
||||
* Copyright (c) 2021, longpanda <admin@ventoy.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Uefi.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/PrintLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DevicePathLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||
#include <Library/UefiApplicationEntryPoint.h>
|
||||
#include <Library/UefiDecompressLib.h>
|
||||
#include <Protocol/LoadedImage.h>
|
||||
#include <Guid/FileInfo.h>
|
||||
#include <Guid/FileSystemInfo.h>
|
||||
#include <Protocol/BlockIo.h>
|
||||
#include <Protocol/RamDisk.h>
|
||||
#include <Protocol/SimpleFileSystem.h>
|
||||
#include <VDiskChain.h>
|
||||
|
||||
BOOLEAN gVDiskDebugPrint = FALSE;
|
||||
vdisk_block_data gVDiskBlockData;
|
||||
|
||||
/* Boot filename */
|
||||
CONST CHAR16 *gEfiBootFileName[] =
|
||||
{
|
||||
L"@",
|
||||
EFI_REMOVABLE_MEDIA_FILE_NAME,
|
||||
#if defined (MDE_CPU_IA32)
|
||||
L"\\EFI\\BOOT\\GRUBIA32.EFI",
|
||||
L"\\EFI\\BOOT\\BOOTia32.EFI",
|
||||
L"\\EFI\\BOOT\\bootia32.efi",
|
||||
L"\\efi\\boot\\bootia32.efi",
|
||||
#elif defined (MDE_CPU_X64)
|
||||
L"\\EFI\\BOOT\\GRUBX64.EFI",
|
||||
L"\\EFI\\BOOT\\BOOTx64.EFI",
|
||||
L"\\EFI\\BOOT\\bootx64.efi",
|
||||
L"\\efi\\boot\\bootx64.efi",
|
||||
#elif defined (MDE_CPU_ARM)
|
||||
L"\\EFI\\BOOT\\GRUBARM.EFI",
|
||||
L"\\EFI\\BOOT\\BOOTarm.EFI",
|
||||
L"\\EFI\\BOOT\\bootarm.efi",
|
||||
L"\\efi\\boot\\bootarm.efi",
|
||||
#elif defined (MDE_CPU_AARCH64)
|
||||
L"\\EFI\\BOOT\\GRUBAA64.EFI",
|
||||
L"\\EFI\\BOOT\\BOOTaa64.EFI",
|
||||
L"\\EFI\\BOOT\\bootaa64.efi",
|
||||
L"\\efi\\boot\\bootaa64.efi",
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
UINT8 *g_disk_buf_addr = NULL;
|
||||
UINT64 g_disk_buf_size = 0;
|
||||
|
||||
STATIC EFI_GET_VARIABLE g_org_get_variable = NULL;
|
||||
STATIC EFI_EXIT_BOOT_SERVICES g_org_exit_boot_service = NULL;
|
||||
|
||||
VOID EFIAPI VDiskDebug(IN CONST CHAR8 *Format, ...)
|
||||
{
|
||||
VA_LIST Marker;
|
||||
CHAR16 Buffer[512];
|
||||
|
||||
VA_START (Marker, Format);
|
||||
UnicodeVSPrintAsciiFormat(Buffer, sizeof(Buffer), Format, Marker);
|
||||
VA_END (Marker);
|
||||
|
||||
gST->ConOut->OutputString(gST->ConOut, Buffer);
|
||||
}
|
||||
|
||||
VOID EFIAPI vdisk_clear_input(VOID)
|
||||
{
|
||||
EFI_INPUT_KEY Key;
|
||||
|
||||
gST->ConIn->Reset(gST->ConIn, FALSE);
|
||||
while (EFI_SUCCESS == gST->ConIn->ReadKeyStroke(gST->ConIn, &Key))
|
||||
{
|
||||
;
|
||||
}
|
||||
gST->ConIn->Reset(gST->ConIn, FALSE);
|
||||
}
|
||||
|
||||
STATIC EFI_STATUS EFIAPI vdisk_load_image
|
||||
(
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *pDevicePath,
|
||||
IN CONST CHAR16 *FileName,
|
||||
IN UINTN FileNameLen,
|
||||
OUT EFI_HANDLE *Image
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
CHAR16 TmpBuf[256] = {0};
|
||||
FILEPATH_DEVICE_PATH *pFilePath = NULL;
|
||||
EFI_DEVICE_PATH_PROTOCOL *pImgPath = NULL;
|
||||
|
||||
pFilePath = (FILEPATH_DEVICE_PATH *)TmpBuf;
|
||||
pFilePath->Header.Type = MEDIA_DEVICE_PATH;
|
||||
pFilePath->Header.SubType = MEDIA_FILEPATH_DP;
|
||||
pFilePath->Header.Length[0] = FileNameLen + sizeof(EFI_DEVICE_PATH_PROTOCOL);
|
||||
pFilePath->Header.Length[1] = 0;
|
||||
CopyMem(pFilePath->PathName, FileName, FileNameLen);
|
||||
|
||||
pImgPath = AppendDevicePathNode(pDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)pFilePath);
|
||||
if (!pImgPath)
|
||||
{
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
Status = gBS->LoadImage(FALSE, ImageHandle, pImgPath, NULL, 0, Image);
|
||||
|
||||
debug("Load Image File %r DP: <%s>", Status, ConvertDevicePathToText(pImgPath, FALSE, FALSE));
|
||||
|
||||
FreePool(pImgPath);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
STATIC EFI_STATUS EFIAPI vdisk_decompress_vdisk(IN EFI_LOADED_IMAGE_PROTOCOL *pImageInfo)
|
||||
{
|
||||
UINT32 Size;
|
||||
UINT32 DestinationSize;
|
||||
UINT32 ScratchSize;
|
||||
UINT8 *buf;
|
||||
VOID *ScratchBuf;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
|
||||
(VOID)pImageInfo;
|
||||
|
||||
vdisk_get_vdisk_raw(&buf, &Size);
|
||||
UefiDecompressGetInfo(buf + VDISK_MAGIC_LEN, Size - VDISK_MAGIC_LEN, &DestinationSize, &ScratchSize);
|
||||
debug("vdisk: size:%u realsize:%u", Size, DestinationSize);
|
||||
|
||||
g_disk_buf_size = DestinationSize;
|
||||
g_disk_buf_addr = AllocatePool(DestinationSize);
|
||||
ScratchBuf = AllocatePool(ScratchSize);
|
||||
|
||||
Status = UefiDecompress(buf + VDISK_MAGIC_LEN, g_disk_buf_addr, ScratchBuf);
|
||||
FreePool(ScratchBuf);
|
||||
|
||||
debug("Status:%r %p %u", Status, g_disk_buf_addr, (UINT32)g_disk_buf_size);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
STATIC EFI_STATUS vdisk_patch_vdisk_path(CHAR16 *pos)
|
||||
{
|
||||
UINTN i;
|
||||
UINTN j;
|
||||
CHAR16 *end;
|
||||
CHAR8 *buf = (char *)g_disk_buf_addr;
|
||||
|
||||
if (*pos == L'\"')
|
||||
{
|
||||
pos++;
|
||||
}
|
||||
|
||||
end = StrStr(pos, L".vtoy");
|
||||
end += 5;//string length
|
||||
|
||||
for (i = 0; i < g_disk_buf_size; i++)
|
||||
{
|
||||
if (*(UINT32 *)(buf + i) == 0x59595959)
|
||||
{
|
||||
for (j = 0; j < 300; j++)
|
||||
{
|
||||
if (buf[i + j] != 'Y')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (j >= 300)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= g_disk_buf_size)
|
||||
{
|
||||
debug("No need to fill vdisk path");
|
||||
return 0;
|
||||
}
|
||||
|
||||
debug("Fill vdisk path at %d", i);
|
||||
|
||||
while (pos != end)
|
||||
{
|
||||
buf[i++] = (CHAR8)(*pos++);
|
||||
}
|
||||
|
||||
buf[i++] = '\"';
|
||||
|
||||
while (buf[i] == 'Y' || buf[i] == '\"')
|
||||
{
|
||||
buf[i] = ' ';
|
||||
i++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI vdisk_get_variable_wrapper
|
||||
(
|
||||
IN CHAR16 *VariableName,
|
||||
IN EFI_GUID *VendorGuid,
|
||||
OUT UINT32 *Attributes, OPTIONAL
|
||||
IN OUT UINTN *DataSize,
|
||||
OUT VOID *Data OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
|
||||
Status = g_org_get_variable(VariableName, VendorGuid, Attributes, DataSize, Data);
|
||||
if (StrCmp(VariableName, L"SecureBoot") == 0)
|
||||
{
|
||||
if ((*DataSize == 1) && Data)
|
||||
{
|
||||
*(UINT8 *)Data = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI vdisk_exit_boot_service_wrapper
|
||||
(
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN UINTN MapKey
|
||||
)
|
||||
{
|
||||
return g_org_exit_boot_service(ImageHandle, MapKey);
|
||||
}
|
||||
|
||||
STATIC EFI_STATUS EFIAPI vdisk_disable_secure_boot(IN EFI_HANDLE ImageHandle)
|
||||
{
|
||||
/* step1: wrapper security protocol. */
|
||||
/* Do we still need it since we have been loaded ? */
|
||||
|
||||
|
||||
/* step2: fake SecureBoot variable */
|
||||
g_org_exit_boot_service = gBS->ExitBootServices;
|
||||
gBS->ExitBootServices = vdisk_exit_boot_service_wrapper;
|
||||
|
||||
g_org_get_variable = gRT->GetVariable;
|
||||
gRT->GetVariable = vdisk_get_variable_wrapper;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
STATIC EFI_STATUS EFIAPI vdisk_parse_cmdline(IN EFI_HANDLE ImageHandle)
|
||||
{
|
||||
CHAR16 *Pos = NULL;
|
||||
CHAR16 *pCmdLine = NULL;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_LOADED_IMAGE_PROTOCOL *pImageInfo = NULL;
|
||||
|
||||
Status = gBS->HandleProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&pImageInfo);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
VDiskDebug("Failed to handle load image protocol %r\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
pCmdLine = (CHAR16 *)AllocatePool(pImageInfo->LoadOptionsSize + 4);
|
||||
SetMem(pCmdLine, pImageInfo->LoadOptionsSize + 4, 0);
|
||||
CopyMem(pCmdLine, pImageInfo->LoadOptions, pImageInfo->LoadOptionsSize);
|
||||
|
||||
if (StrStr(pCmdLine, L"debug"))
|
||||
{
|
||||
gVDiskDebugPrint = TRUE;
|
||||
}
|
||||
|
||||
debug("cmdline:<%s>", pCmdLine);
|
||||
vdisk_debug_pause();
|
||||
|
||||
Pos = StrStr(pCmdLine, L"vdisk=");
|
||||
if (NULL == Pos || NULL == StrStr(pCmdLine, L".vtoy"))
|
||||
{
|
||||
VDiskDebug("vdisk parameter not found!\n");
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
vdisk_decompress_vdisk(pImageInfo);
|
||||
|
||||
vdisk_patch_vdisk_path(Pos + 6);
|
||||
|
||||
if (StrStr(pCmdLine, L"secureboot=off"))
|
||||
{
|
||||
vdisk_disable_secure_boot(ImageHandle);
|
||||
}
|
||||
|
||||
FreePool(pCmdLine);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI vdisk_boot(IN EFI_HANDLE ImageHandle)
|
||||
{
|
||||
UINTN t = 0;
|
||||
UINTN i = 0;
|
||||
UINTN j = 0;
|
||||
UINTN Find = 0;
|
||||
UINTN Count = 0;
|
||||
EFI_HANDLE Image = NULL;
|
||||
EFI_HANDLE *Handles = NULL;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *pFile = NULL;
|
||||
EFI_DEVICE_PATH_PROTOCOL *pDevPath = NULL;
|
||||
|
||||
for (t = 0; t < 3; t++)
|
||||
{
|
||||
Count = 0;
|
||||
Handles = NULL;
|
||||
|
||||
Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiSimpleFileSystemProtocolGuid,
|
||||
NULL, &Count, &Handles);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
debug("vdisk_boot fs count:%u", Count);
|
||||
|
||||
for (i = 0; i < Count; i++)
|
||||
{
|
||||
Status = gBS->HandleProtocol(Handles[i], &gEfiSimpleFileSystemProtocolGuid, (VOID **)&pFile);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
debug("FS:%u Protocol:%p OpenVolume:%p", i, pFile, pFile->OpenVolume);
|
||||
|
||||
Status = gBS->OpenProtocol(Handles[i], &gEfiDevicePathProtocolGuid,
|
||||
(VOID **)&pDevPath,
|
||||
ImageHandle,
|
||||
Handles[i],
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
debug("Failed to open device path protocol %r", Status);
|
||||
continue;
|
||||
}
|
||||
|
||||
debug("Handle:%p FS DP: <%s>", Handles[i], ConvertDevicePathToText(pDevPath, FALSE, FALSE));
|
||||
if (CompareMem(gVDiskBlockData.Path, pDevPath, gVDiskBlockData.DevicePathCompareLen))
|
||||
{
|
||||
debug("Not ventoy disk file system");
|
||||
continue;
|
||||
}
|
||||
|
||||
for (j = 1; j < ARRAY_SIZE(gEfiBootFileName); j++)
|
||||
{
|
||||
Status = vdisk_load_image(ImageHandle, pDevPath, gEfiBootFileName[j],
|
||||
StrSize(gEfiBootFileName[j]), &Image);
|
||||
if (EFI_SUCCESS == Status)
|
||||
{
|
||||
break;
|
||||
}
|
||||
debug("Failed to load image %r <%s>", Status, gEfiBootFileName[j]);
|
||||
}
|
||||
|
||||
if (j >= ARRAY_SIZE(gEfiBootFileName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Find++;
|
||||
debug("Find boot file, now try to boot .....");
|
||||
vdisk_debug_pause();
|
||||
|
||||
if (gVDiskDebugPrint)
|
||||
{
|
||||
gST->ConIn->Reset(gST->ConIn, FALSE);
|
||||
}
|
||||
|
||||
/* can't add debug print here */
|
||||
//ventoy_wrapper_system();
|
||||
Status = gBS->StartImage(Image, NULL, NULL);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
debug("Failed to start image %r", Status);
|
||||
sleep(3);
|
||||
gBS->UnloadImage(Image);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FreePool(Handles);
|
||||
|
||||
if (Find == 0)
|
||||
{
|
||||
debug("Fs not found, now wait and retry...");
|
||||
sleep(2);
|
||||
}
|
||||
}
|
||||
|
||||
if (Find == 0)
|
||||
{
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI VDiskChainEfiMain
|
||||
(
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
|
||||
gST->ConOut->ClearScreen(gST->ConOut);
|
||||
vdisk_clear_input();
|
||||
|
||||
Status = vdisk_parse_cmdline(ImageHandle);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
vdisk_install_blockio(ImageHandle, g_disk_buf_size);
|
||||
vdisk_debug_pause();
|
||||
|
||||
Status = vdisk_boot(ImageHandle);
|
||||
|
||||
gBS->DisconnectController(gVDiskBlockData.Handle, NULL, NULL);
|
||||
gBS->UninstallMultipleProtocolInterfaces(gVDiskBlockData.Handle,
|
||||
&gEfiBlockIoProtocolGuid, &gVDiskBlockData.BlockIo,
|
||||
&gEfiDevicePathProtocolGuid, gVDiskBlockData.Path,
|
||||
NULL);
|
||||
|
||||
if (EFI_NOT_FOUND == Status)
|
||||
{
|
||||
gST->ConOut->OutputString(gST->ConOut, L"No bootfile found for UEFI!\r\n");
|
||||
gST->ConOut->OutputString(gST->ConOut, L"Maybe the image does not support " VENTOY_UEFI_DESC L"!\r\n");
|
||||
sleep(30);
|
||||
}
|
||||
|
||||
vdisk_clear_input();
|
||||
gST->ConOut->ClearScreen(gST->ConOut);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
@ -0,0 +1,97 @@
|
||||
/******************************************************************************
|
||||
* VDiskChain.h
|
||||
*
|
||||
* Copyright (c) 2021, longpanda <admin@ventoy.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __VENTOY_H__
|
||||
#define __VENTOY_H__
|
||||
|
||||
#define VDISK_MAGIC_LEN 32
|
||||
|
||||
#define VDISK_BLOCK_DEVICE_PATH_GUID \
|
||||
{ 0x6ed2134e, 0xc2ea, 0x4943, { 0x99, 0x54, 0xa7, 0x76, 0xe5, 0x9c, 0x12, 0xc3 }}
|
||||
|
||||
#define VDISK_BLOCK_DEVICE_PATH_NAME L"vdisk"
|
||||
|
||||
#if defined (MDE_CPU_IA32)
|
||||
#define VENTOY_UEFI_DESC L"IA32 UEFI"
|
||||
#elif defined (MDE_CPU_X64)
|
||||
#define VENTOY_UEFI_DESC L"X64 UEFI"
|
||||
#elif defined (MDE_CPU_EBC)
|
||||
#elif defined (MDE_CPU_ARM)
|
||||
#define VENTOY_UEFI_DESC L"ARM UEFI"
|
||||
#elif defined (MDE_CPU_AARCH64)
|
||||
#define VENTOY_UEFI_DESC L"ARM64 UEFI"
|
||||
#else
|
||||
#error Unknown Processor Type
|
||||
#endif
|
||||
|
||||
typedef struct vdisk_block_data
|
||||
{
|
||||
EFI_HANDLE Handle;
|
||||
EFI_BLOCK_IO_MEDIA Media; /* Media descriptor */
|
||||
EFI_BLOCK_IO_PROTOCOL BlockIo; /* Block I/O protocol */
|
||||
|
||||
UINTN DevicePathCompareLen;
|
||||
EFI_DEVICE_PATH_PROTOCOL *Path; /* Device path protocol */
|
||||
|
||||
EFI_HANDLE RawBlockIoHandle;
|
||||
EFI_BLOCK_IO_PROTOCOL *pRawBlockIo;
|
||||
EFI_DEVICE_PATH_PROTOCOL *pDiskDevPath;
|
||||
|
||||
/* ventoy disk part2 ESP */
|
||||
EFI_HANDLE DiskFsHandle;
|
||||
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *pDiskFs;
|
||||
EFI_DEVICE_PATH_PROTOCOL *pDiskFsDevPath;
|
||||
|
||||
EFI_HANDLE IsoDriverImage;
|
||||
}vdisk_block_data;
|
||||
|
||||
|
||||
#define debug(expr, ...) if (gVDiskDebugPrint) VDiskDebug("[VDISK] "expr"\r\n", ##__VA_ARGS__)
|
||||
#define trace(expr, ...) VDiskDebug("[VDISK] "expr"\r\n", ##__VA_ARGS__)
|
||||
#define sleep(sec) gBS->Stall(1000000 * (sec))
|
||||
|
||||
#define vdisk_debug_pause() \
|
||||
if (gVDiskDebugPrint) \
|
||||
{ \
|
||||
UINTN __Index = 0; \
|
||||
gST->ConOut->OutputString(gST->ConOut, L"[VDISK] ###### Press Enter to continue... ######\r\n");\
|
||||
gST->ConIn->Reset(gST->ConIn, FALSE); \
|
||||
gBS->WaitForEvent(1, &gST->ConIn->WaitForKey, &__Index);\
|
||||
}
|
||||
|
||||
extern BOOLEAN gVDiskDebugPrint;
|
||||
VOID EFIAPI VDiskDebug(IN CONST CHAR8 *Format, ...);
|
||||
EFI_STATUS EFIAPI vdisk_block_io_read
|
||||
(
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSize,
|
||||
OUT VOID *Buffer
|
||||
);
|
||||
|
||||
extern UINT8 *g_disk_buf_addr;
|
||||
extern UINT64 g_disk_buf_size;
|
||||
extern vdisk_block_data gVDiskBlockData;
|
||||
EFI_STATUS EFIAPI vdisk_install_blockio(IN EFI_HANDLE ImageHandle, IN UINT64 ImgSize);
|
||||
int vdisk_get_vdisk_raw(UINT8 **buf, UINT32 *size);
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,82 @@
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = VDiskChain
|
||||
FILE_GUID = 5bce96e3-ba11-4440-833b-299cf5849193
|
||||
MODULE_TYPE = UEFI_APPLICATION
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = VDiskChainEfiMain
|
||||
|
||||
|
||||
[Sources]
|
||||
VDiskChain.h
|
||||
VDiskChain.c
|
||||
VDiskRawData.c
|
||||
VDiskChainProtocol.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
ShellPkg/ShellPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
UefiApplicationEntryPoint
|
||||
UefiLib
|
||||
DebugLib
|
||||
UefiDecompressLib
|
||||
|
||||
[Guids]
|
||||
gShellVariableGuid
|
||||
gEfiVirtualCdGuid
|
||||
gEfiFileInfoGuid
|
||||
|
||||
[Protocols]
|
||||
gEfiLoadedImageProtocolGuid
|
||||
gEfiBlockIoProtocolGuid
|
||||
gEfiDevicePathProtocolGuid
|
||||
gEfiSimpleFileSystemProtocolGuid
|
||||
gEfiRamDiskProtocolGuid
|
||||
gEfiAbsolutePointerProtocolGuid
|
||||
gEfiAcpiTableProtocolGuid
|
||||
gEfiBlockIo2ProtocolGuid
|
||||
gEfiBusSpecificDriverOverrideProtocolGuid
|
||||
gEfiComponentNameProtocolGuid
|
||||
gEfiComponentName2ProtocolGuid
|
||||
gEfiDriverBindingProtocolGuid
|
||||
gEfiDiskIoProtocolGuid
|
||||
gEfiDiskIo2ProtocolGuid
|
||||
gEfiGraphicsOutputProtocolGuid
|
||||
gEfiHiiConfigAccessProtocolGuid
|
||||
gEfiHiiFontProtocolGuid
|
||||
gEfiLoadFileProtocolGuid
|
||||
gEfiLoadFile2ProtocolGuid
|
||||
gEfiLoadedImageProtocolGuid
|
||||
gEfiLoadedImageDevicePathProtocolGuid
|
||||
gEfiPciIoProtocolGuid
|
||||
gEfiSerialIoProtocolGuid
|
||||
gEfiSimpleTextInProtocolGuid
|
||||
gEfiSimpleTextInputExProtocolGuid
|
||||
gEfiSimpleTextOutProtocolGuid
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,264 @@
|
||||
/******************************************************************************
|
||||
* VDiskChainProtocol.c
|
||||
*
|
||||
* Copyright (c) 2021, longpanda <admin@ventoy.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Uefi.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/PrintLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DevicePathLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||
#include <Library/UefiApplicationEntryPoint.h>
|
||||
#include <Protocol/LoadedImage.h>
|
||||
#include <Guid/FileInfo.h>
|
||||
#include <Guid/FileSystemInfo.h>
|
||||
#include <Protocol/BlockIo.h>
|
||||
#include <Protocol/RamDisk.h>
|
||||
#include <Protocol/SimpleFileSystem.h>
|
||||
#include <VDiskChain.h>
|
||||
|
||||
/* EFI block device vendor device path GUID */
|
||||
EFI_GUID gVDiskBlockDevicePathGuid = VDISK_BLOCK_DEVICE_PATH_GUID;
|
||||
|
||||
EFI_STATUS EFIAPI vdisk_block_io_reset
|
||||
(
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN BOOLEAN ExtendedVerification
|
||||
)
|
||||
{
|
||||
(VOID)This;
|
||||
(VOID)ExtendedVerification;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI vdisk_block_io_flush(IN EFI_BLOCK_IO_PROTOCOL *This)
|
||||
{
|
||||
(VOID)This;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI vdisk_block_io_read
|
||||
(
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSize,
|
||||
OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
(VOID)This;
|
||||
(VOID)MediaId;
|
||||
|
||||
debug("vdisk_block_io_read %lu %lu\n", Lba, BufferSize / 512);
|
||||
CopyMem(Buffer, g_disk_buf_addr + (Lba * 512), BufferSize);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI vdisk_block_io_write
|
||||
(
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSize,
|
||||
IN VOID *Buffer
|
||||
)
|
||||
{
|
||||
(VOID)This;
|
||||
(VOID)MediaId;
|
||||
(VOID)Buffer;
|
||||
|
||||
debug("vdisk_block_io_read %lu %lu\n", Lba, BufferSize / 512);
|
||||
return EFI_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI vdisk_fill_device_path(VOID)
|
||||
{
|
||||
UINTN NameLen = 0;
|
||||
UINT8 TmpBuf[128] = {0};
|
||||
VENDOR_DEVICE_PATH *venPath = NULL;
|
||||
|
||||
venPath = (VENDOR_DEVICE_PATH *)TmpBuf;
|
||||
NameLen = StrSize(VDISK_BLOCK_DEVICE_PATH_NAME);
|
||||
venPath->Header.Type = HARDWARE_DEVICE_PATH;
|
||||
venPath->Header.SubType = HW_VENDOR_DP;
|
||||
venPath->Header.Length[0] = sizeof(VENDOR_DEVICE_PATH) + NameLen;
|
||||
venPath->Header.Length[1] = 0;
|
||||
CopyMem(&venPath->Guid, &gVDiskBlockDevicePathGuid, sizeof(EFI_GUID));
|
||||
CopyMem(venPath + 1, VDISK_BLOCK_DEVICE_PATH_NAME, NameLen);
|
||||
|
||||
gVDiskBlockData.Path = AppendDevicePathNode(NULL, (EFI_DEVICE_PATH_PROTOCOL *)TmpBuf);
|
||||
gVDiskBlockData.DevicePathCompareLen = sizeof(VENDOR_DEVICE_PATH) + NameLen;
|
||||
|
||||
debug("gVDiskBlockData.Path=<%s>\n", ConvertDevicePathToText(gVDiskBlockData.Path, FALSE, FALSE));
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI vdisk_connect_driver(IN EFI_HANDLE ControllerHandle, IN CONST CHAR16 *DrvName)
|
||||
{
|
||||
UINTN i = 0;
|
||||
UINTN Count = 0;
|
||||
CHAR16 *DriverName = NULL;
|
||||
EFI_HANDLE *Handles = NULL;
|
||||
EFI_HANDLE DrvHandles[2] = { NULL };
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_COMPONENT_NAME_PROTOCOL *NameProtocol = NULL;
|
||||
EFI_COMPONENT_NAME2_PROTOCOL *Name2Protocol = NULL;
|
||||
|
||||
debug("vdisk_connect_driver <%s>...", DrvName);
|
||||
|
||||
Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiComponentName2ProtocolGuid,
|
||||
NULL, &Count, &Handles);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
for (i = 0; i < Count; i++)
|
||||
{
|
||||
Status = gBS->HandleProtocol(Handles[i], &gEfiComponentName2ProtocolGuid, (VOID **)&Name2Protocol);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Status = Name2Protocol->GetDriverName(Name2Protocol, "en", &DriverName);
|
||||
if (EFI_ERROR(Status) || NULL == DriverName)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (StrStr(DriverName, DrvName))
|
||||
{
|
||||
debug("Find driver name2:<%s>: <%s>", DriverName, DrvName);
|
||||
DrvHandles[0] = Handles[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < Count)
|
||||
{
|
||||
Status = gBS->ConnectController(ControllerHandle, DrvHandles, NULL, TRUE);
|
||||
debug("vdisk_connect_driver:<%s> <%r>", DrvName, Status);
|
||||
goto end;
|
||||
}
|
||||
|
||||
debug("%s NOT found, now try COMPONENT_NAME", DrvName);
|
||||
|
||||
Count = 0;
|
||||
FreePool(Handles);
|
||||
Handles = NULL;
|
||||
|
||||
Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiComponentNameProtocolGuid,
|
||||
NULL, &Count, &Handles);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
for (i = 0; i < Count; i++)
|
||||
{
|
||||
Status = gBS->HandleProtocol(Handles[i], &gEfiComponentNameProtocolGuid, (VOID **)&NameProtocol);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Status = NameProtocol->GetDriverName(NameProtocol, "en", &DriverName);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (StrStr(DriverName, DrvName))
|
||||
{
|
||||
debug("Find driver name:<%s>: <%s>", DriverName, DrvName);
|
||||
DrvHandles[0] = Handles[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < Count)
|
||||
{
|
||||
Status = gBS->ConnectController(ControllerHandle, DrvHandles, NULL, TRUE);
|
||||
debug("vdisk_connect_driver:<%s> <%r>", DrvName, Status);
|
||||
goto end;
|
||||
}
|
||||
|
||||
Status = EFI_NOT_FOUND;
|
||||
|
||||
end:
|
||||
FreePool(Handles);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI vdisk_install_blockio(IN EFI_HANDLE ImageHandle, IN UINT64 ImgSize)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_BLOCK_IO_PROTOCOL *pBlockIo = &(gVDiskBlockData.BlockIo);
|
||||
|
||||
vdisk_fill_device_path();
|
||||
|
||||
debug("install block io protocol %p", ImageHandle);
|
||||
vdisk_debug_pause();
|
||||
|
||||
gVDiskBlockData.Media.BlockSize = 512;
|
||||
gVDiskBlockData.Media.LastBlock = ImgSize / 512 - 1;
|
||||
gVDiskBlockData.Media.ReadOnly = TRUE;
|
||||
gVDiskBlockData.Media.MediaPresent = 1;
|
||||
gVDiskBlockData.Media.LogicalBlocksPerPhysicalBlock = 1;
|
||||
|
||||
pBlockIo->Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3;
|
||||
pBlockIo->Media = &(gVDiskBlockData.Media);
|
||||
pBlockIo->Reset = vdisk_block_io_reset;
|
||||
pBlockIo->ReadBlocks = vdisk_block_io_read;
|
||||
pBlockIo->WriteBlocks = vdisk_block_io_write;
|
||||
pBlockIo->FlushBlocks = vdisk_block_io_flush;
|
||||
|
||||
Status = gBS->InstallMultipleProtocolInterfaces(&gVDiskBlockData.Handle,
|
||||
&gEfiBlockIoProtocolGuid, &gVDiskBlockData.BlockIo,
|
||||
&gEfiDevicePathProtocolGuid, gVDiskBlockData.Path,
|
||||
NULL);
|
||||
debug("Install protocol %r %p", Status, gVDiskBlockData.Handle);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = vdisk_connect_driver(gVDiskBlockData.Handle, L"Disk I/O Driver");
|
||||
debug("Connect disk IO driver %r", Status);
|
||||
|
||||
Status = vdisk_connect_driver(gVDiskBlockData.Handle, L"Partition Driver");
|
||||
debug("Connect partition driver %r", Status);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
Status = gBS->ConnectController(gVDiskBlockData.Handle, NULL, NULL, TRUE);
|
||||
debug("Connect all controller %r", Status);
|
||||
}
|
||||
|
||||
vdisk_debug_pause();
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
@ -0,0 +1,2 @@
|
||||
#include <Uefi.h>
|
||||
int vdisk_get_vdisk_raw(UINT8 **buf, UINT32 *size) { *buf = NULL; *size = 0; return 0; }
|
@ -34,11 +34,17 @@
|
||||
#include <Protocol/BlockIo.h>
|
||||
#include <Protocol/RamDisk.h>
|
||||
#include <Protocol/SimpleFileSystem.h>
|
||||
#include <Protocol/DriverBinding.h>
|
||||
#include <Ventoy.h>
|
||||
|
||||
BOOLEAN gDebugPrint = FALSE;
|
||||
BOOLEAN gBootFallBack = FALSE;
|
||||
BOOLEAN gDotEfiBoot = FALSE;
|
||||
BOOLEAN gLoadIsoEfi = FALSE;
|
||||
BOOLEAN gIsoUdf = FALSE;
|
||||
ventoy_ram_disk g_ramdisk_param;
|
||||
ventoy_chain_head *g_chain;
|
||||
void *g_vtoy_img_location_buf;
|
||||
ventoy_img_chunk *g_chunk;
|
||||
UINT8 *g_os_param_reserved;
|
||||
UINT32 g_img_chunk_num;
|
||||
@ -48,10 +54,16 @@ ventoy_virt_chunk *g_virt_chunk;
|
||||
UINT32 g_virt_chunk_num;
|
||||
vtoy_block_data gBlockData;
|
||||
static grub_env_get_pf grub_env_get = NULL;
|
||||
static grub_env_set_pf grub_env_set = NULL;
|
||||
|
||||
ventoy_grub_param_file_replace *g_file_replace_list = NULL;
|
||||
ventoy_efi_file_replace g_efi_file_replace;
|
||||
|
||||
CONST CHAR16 gIso9660EfiDriverPath[] = ISO9660_EFI_DRIVER_PATH;
|
||||
CONST CHAR16 gUdfEfiDriverPath[] = UDF_EFI_DRIVER_PATH;
|
||||
|
||||
BOOLEAN g_fix_windows_1st_cdrom_issue = FALSE;
|
||||
|
||||
STATIC BOOLEAN g_hook_keyboard = FALSE;
|
||||
|
||||
CHAR16 gFirstTryBootFile[256] = {0};
|
||||
@ -62,10 +74,28 @@ CONST CHAR16 *gEfiBootFileName[] =
|
||||
{
|
||||
L"@",
|
||||
EFI_REMOVABLE_MEDIA_FILE_NAME,
|
||||
#if defined (MDE_CPU_IA32)
|
||||
L"\\EFI\\BOOT\\GRUBIA32.EFI",
|
||||
L"\\EFI\\BOOT\\BOOTia32.EFI",
|
||||
L"\\EFI\\BOOT\\bootia32.efi",
|
||||
L"\\efi\\boot\\bootia32.efi",
|
||||
#elif defined (MDE_CPU_X64)
|
||||
L"\\EFI\\BOOT\\GRUBX64.EFI",
|
||||
L"\\EFI\\BOOT\\BOOTx64.EFI",
|
||||
L"\\EFI\\BOOT\\bootx64.efi",
|
||||
L"\\efi\\boot\\bootx64.efi",
|
||||
#elif defined (MDE_CPU_ARM)
|
||||
L"\\EFI\\BOOT\\GRUBARM.EFI",
|
||||
L"\\EFI\\BOOT\\BOOTarm.EFI",
|
||||
L"\\EFI\\BOOT\\bootarm.efi",
|
||||
L"\\efi\\boot\\bootarm.efi",
|
||||
#elif defined (MDE_CPU_AARCH64)
|
||||
L"\\EFI\\BOOT\\GRUBAA64.EFI",
|
||||
L"\\EFI\\BOOT\\BOOTaa64.EFI",
|
||||
L"\\EFI\\BOOT\\bootaa64.efi",
|
||||
L"\\efi\\boot\\bootaa64.efi",
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
VOID EFIAPI VtoyDebug(IN CONST CHAR8 *Format, ...)
|
||||
@ -242,6 +272,7 @@ static int ventoy_update_image_location(ventoy_os_param *param)
|
||||
}
|
||||
|
||||
address = (UINTN)buffer;
|
||||
g_vtoy_img_location_buf = buffer;
|
||||
|
||||
if (address % 4096)
|
||||
{
|
||||
@ -266,19 +297,33 @@ static int ventoy_update_image_location(ventoy_os_param *param)
|
||||
}
|
||||
|
||||
CopyMem(&location->guid, ¶m->guid, sizeof(ventoy_guid));
|
||||
location->image_sector_size = 2048;
|
||||
location->image_sector_size = gSector512Mode ? 512 : 2048;
|
||||
location->disk_sector_size = g_chain->disk_sector_size;
|
||||
location->region_count = g_img_chunk_num;
|
||||
|
||||
region = location->regions;
|
||||
|
||||
for (i = 0; i < g_img_chunk_num; i++)
|
||||
if (gSector512Mode)
|
||||
{
|
||||
region->image_sector_count = chunk->img_end_sector - chunk->img_start_sector + 1;
|
||||
region->image_start_sector = chunk->img_start_sector;
|
||||
region->disk_start_sector = chunk->disk_start_sector;
|
||||
region++;
|
||||
chunk++;
|
||||
for (i = 0; i < g_img_chunk_num; i++)
|
||||
{
|
||||
region->image_sector_count = chunk->disk_end_sector - chunk->disk_start_sector + 1;
|
||||
region->image_start_sector = chunk->img_start_sector * 4;
|
||||
region->disk_start_sector = chunk->disk_start_sector;
|
||||
region++;
|
||||
chunk++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < g_img_chunk_num; i++)
|
||||
{
|
||||
region->image_sector_count = chunk->img_end_sector - chunk->img_start_sector + 1;
|
||||
region->image_start_sector = chunk->img_start_sector;
|
||||
region->disk_start_sector = chunk->disk_start_sector;
|
||||
region++;
|
||||
chunk++;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -318,15 +363,27 @@ EFI_HANDLE EFIAPI ventoy_get_parent_handle(IN EFI_DEVICE_PATH_PROTOCOL *pDevPath
|
||||
return Handle;
|
||||
}
|
||||
|
||||
STATIC ventoy_ram_disk g_backup_ramdisk_param;
|
||||
STATIC ventoy_os_param g_backup_os_param_var;
|
||||
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_save_ramdisk_param(VOID)
|
||||
{
|
||||
UINTN DataSize;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_GUID VarGuid = VENTOY_GUID;
|
||||
|
||||
DataSize = sizeof(g_backup_ramdisk_param);
|
||||
Status = gRT->GetVariable(L"VentoyRamDisk", &VarGuid, NULL, &DataSize, &g_backup_ramdisk_param);
|
||||
if (!EFI_ERROR(Status))
|
||||
{
|
||||
debug("find previous ramdisk variable <%llu>", g_backup_ramdisk_param.DiskSize);
|
||||
}
|
||||
|
||||
Status = gRT->SetVariable(L"VentoyRamDisk", &VarGuid,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
|
||||
sizeof(g_ramdisk_param), &(g_ramdisk_param));
|
||||
debug("set efi variable %r", Status);
|
||||
debug("set ramdisk variable %r", Status);
|
||||
|
||||
return Status;
|
||||
}
|
||||
@ -335,21 +392,38 @@ EFI_STATUS EFIAPI ventoy_delete_ramdisk_param(VOID)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_GUID VarGuid = VENTOY_GUID;
|
||||
|
||||
Status = gRT->SetVariable(L"VentoyRamDisk", &VarGuid,
|
||||
|
||||
if (g_backup_ramdisk_param.DiskSize > 0 && g_backup_ramdisk_param.PhyAddr > 0)
|
||||
{
|
||||
Status = gRT->SetVariable(L"VentoyRamDisk", &VarGuid,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
|
||||
sizeof(g_backup_ramdisk_param), &g_backup_ramdisk_param);
|
||||
debug("resotre ramdisk variable %r", Status);
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = gRT->SetVariable(L"VentoyRamDisk", &VarGuid,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
|
||||
0, NULL);
|
||||
debug("delete efi variable %r", Status);
|
||||
debug("delete ramdisk variable %r", Status);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_save_variable(VOID)
|
||||
{
|
||||
UINTN DataSize;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_GUID VarGuid = VENTOY_GUID;
|
||||
|
||||
|
||||
DataSize = sizeof(g_backup_os_param_var);
|
||||
Status = gRT->GetVariable(L"VentoyOsParam", &VarGuid, NULL, &DataSize, &g_backup_os_param_var);
|
||||
if (!EFI_ERROR(Status))
|
||||
{
|
||||
debug("find previous efi variable <%a>", g_backup_os_param_var.vtoy_img_path);
|
||||
}
|
||||
|
||||
Status = gRT->SetVariable(L"VentoyOsParam", &VarGuid,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
|
||||
sizeof(g_chain->os_param), &(g_chain->os_param));
|
||||
@ -362,15 +436,55 @@ EFI_STATUS EFIAPI ventoy_delete_variable(VOID)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_GUID VarGuid = VENTOY_GUID;
|
||||
|
||||
Status = gRT->SetVariable(L"VentoyOsParam", &VarGuid,
|
||||
|
||||
if (0 == CompareMem(&(g_backup_os_param_var.guid), &VarGuid, sizeof(EFI_GUID)))
|
||||
{
|
||||
Status = gRT->SetVariable(L"VentoyOsParam", &VarGuid,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
|
||||
sizeof(g_backup_os_param_var), &(g_backup_os_param_var));
|
||||
debug("restore efi variable %r", Status);
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = gRT->SetVariable(L"VentoyOsParam", &VarGuid,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
|
||||
0, NULL);
|
||||
debug("delete efi variable %r", Status);
|
||||
debug("delete efi variable %r", Status);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
#if (VENTOY_DEVICE_WARN != 0)
|
||||
STATIC VOID ventoy_warn_invalid_device(VOID)
|
||||
{
|
||||
STATIC BOOLEAN flag = FALSE;
|
||||
|
||||
if (flag)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
flag = TRUE;
|
||||
gST->ConOut->ClearScreen(gST->ConOut);
|
||||
gST->ConOut->OutputString(gST->ConOut, VTOY_WARNING L"\r\n");
|
||||
gST->ConOut->OutputString(gST->ConOut, VTOY_WARNING L"\r\n");
|
||||
gST->ConOut->OutputString(gST->ConOut, VTOY_WARNING L"\r\n\r\n\r\n");
|
||||
|
||||
gST->ConOut->OutputString(gST->ConOut, L"This is NOT a standard Ventoy device and is NOT supported.\r\n\r\n");
|
||||
gST->ConOut->OutputString(gST->ConOut, L"You should follow the official instructions in https://www.ventoy.net\r\n");
|
||||
|
||||
gST->ConOut->OutputString(gST->ConOut, L"\r\n\r\nWill exit after 10 seconds ...... ");
|
||||
|
||||
sleep(10);
|
||||
}
|
||||
#else
|
||||
STATIC VOID ventoy_warn_invalid_device(VOID)
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
STATIC EFI_STATUS EFIAPI ventoy_load_image
|
||||
(
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
@ -413,6 +527,7 @@ STATIC EFI_STATUS EFIAPI ventoy_find_iso_disk(IN EFI_HANDLE ImageHandle)
|
||||
UINTN i = 0;
|
||||
UINTN Count = 0;
|
||||
UINT64 DiskSize = 0;
|
||||
MBR_HEAD *pMBR = NULL;
|
||||
UINT8 *pBuffer = NULL;
|
||||
EFI_HANDLE *Handles;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
@ -456,6 +571,18 @@ STATIC EFI_STATUS EFIAPI ventoy_find_iso_disk(IN EFI_HANDLE ImageHandle)
|
||||
|
||||
if (CompareMem(g_chain->os_param.vtoy_disk_guid, pBuffer + 0x180, 16) == 0)
|
||||
{
|
||||
pMBR = (MBR_HEAD *)pBuffer;
|
||||
if (pMBR->PartTbl[0].FsFlag != 0xEE)
|
||||
{
|
||||
if (pMBR->PartTbl[0].StartSectorId != 2048 ||
|
||||
pMBR->PartTbl[1].SectorCount != 65536 ||
|
||||
pMBR->PartTbl[1].StartSectorId != pMBR->PartTbl[0].StartSectorId + pMBR->PartTbl[0].SectorCount)
|
||||
{
|
||||
debug("Failed to check disk part table");
|
||||
ventoy_warn_invalid_device();
|
||||
}
|
||||
}
|
||||
|
||||
gBlockData.RawBlockIoHandle = Handles[i];
|
||||
gBlockData.pRawBlockIo = pBlockIo;
|
||||
gBS->OpenProtocol(Handles[i], &gEfiDevicePathProtocolGuid,
|
||||
@ -482,17 +609,117 @@ STATIC EFI_STATUS EFIAPI ventoy_find_iso_disk(IN EFI_HANDLE ImageHandle)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
STATIC EFI_STATUS EFIAPI ventoy_find_iso_disk_fs(IN EFI_HANDLE ImageHandle)
|
||||
{
|
||||
UINTN i = 0;
|
||||
UINTN Count = 0;
|
||||
EFI_HANDLE Parent = NULL;
|
||||
EFI_HANDLE *Handles = NULL;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *pFile = NULL;
|
||||
EFI_DEVICE_PATH_PROTOCOL *pDevPath = NULL;
|
||||
|
||||
Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiSimpleFileSystemProtocolGuid,
|
||||
NULL, &Count, &Handles);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
debug("ventoy_find_iso_disk_fs fs count:%u", Count);
|
||||
|
||||
for (i = 0; i < Count; i++)
|
||||
{
|
||||
Status = gBS->HandleProtocol(Handles[i], &gEfiSimpleFileSystemProtocolGuid, (VOID **)&pFile);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Status = gBS->OpenProtocol(Handles[i], &gEfiDevicePathProtocolGuid,
|
||||
(VOID **)&pDevPath,
|
||||
ImageHandle,
|
||||
Handles[i],
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
debug("Failed to open device path protocol %r", Status);
|
||||
continue;
|
||||
}
|
||||
|
||||
debug("Handle:%p FS DP: <%s>", Handles[i], ConvertDevicePathToText(pDevPath, FALSE, FALSE));
|
||||
Parent = ventoy_get_parent_handle(pDevPath);
|
||||
|
||||
if (Parent == gBlockData.RawBlockIoHandle)
|
||||
{
|
||||
debug("Find ventoy disk fs");
|
||||
gBlockData.DiskFsHandle = Handles[i];
|
||||
gBlockData.pDiskFs = pFile;
|
||||
gBlockData.pDiskFsDevPath = pDevPath;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FreePool(Handles);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
STATIC EFI_STATUS EFIAPI ventoy_load_isoefi_driver(IN EFI_HANDLE ImageHandle)
|
||||
{
|
||||
EFI_HANDLE Image = NULL;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
CHAR16 LogVar[4] = L"5";
|
||||
|
||||
if (gIsoUdf)
|
||||
{
|
||||
Status = ventoy_load_image(ImageHandle, gBlockData.pDiskFsDevPath,
|
||||
gUdfEfiDriverPath,
|
||||
sizeof(gUdfEfiDriverPath),
|
||||
&Image);
|
||||
debug("load iso UDF efi driver status:%r", Status);
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = ventoy_load_image(ImageHandle, gBlockData.pDiskFsDevPath,
|
||||
gIso9660EfiDriverPath,
|
||||
sizeof(gIso9660EfiDriverPath),
|
||||
&Image);
|
||||
debug("load iso 9660 efi driver status:%r", Status);
|
||||
}
|
||||
|
||||
if (gDebugPrint)
|
||||
{
|
||||
gRT->SetVariable(L"FS_LOGGING", &gShellVariableGuid,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
|
||||
sizeof(LogVar), LogVar);
|
||||
}
|
||||
|
||||
gRT->SetVariable(L"FS_NAME_NOCASE", &gShellVariableGuid,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
|
||||
sizeof(LogVar), LogVar);
|
||||
|
||||
gBlockData.IsoDriverImage = Image;
|
||||
Status = gBS->StartImage(Image, NULL, NULL);
|
||||
debug("Start iso efi driver status:%r", Status);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
|
||||
{
|
||||
UINT32 i = 0;
|
||||
UINT32 old_cnt = 0;
|
||||
UINTN size = 0;
|
||||
UINT8 chksum = 0;
|
||||
const char *pEnv = NULL;
|
||||
CHAR16 *pPos = NULL;
|
||||
CHAR16 *pCmdLine = NULL;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
ventoy_grub_param *pGrubParam = NULL;
|
||||
EFI_LOADED_IMAGE_PROTOCOL *pImageInfo = NULL;
|
||||
ventoy_chain_head *chain = NULL;
|
||||
|
||||
Status = gBS->HandleProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&pImageInfo);
|
||||
if (EFI_ERROR(Status))
|
||||
@ -509,6 +736,26 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
|
||||
{
|
||||
gDebugPrint = TRUE;
|
||||
}
|
||||
|
||||
if (StrStr(pCmdLine, L"fallback"))
|
||||
{
|
||||
gBootFallBack = TRUE;
|
||||
}
|
||||
|
||||
if (StrStr(pCmdLine, L"dotefi"))
|
||||
{
|
||||
gDotEfiBoot = TRUE;
|
||||
}
|
||||
|
||||
if (StrStr(pCmdLine, L"isoefi=on"))
|
||||
{
|
||||
gLoadIsoEfi = TRUE;
|
||||
}
|
||||
|
||||
if (StrStr(pCmdLine, L"iso_udf"))
|
||||
{
|
||||
gIsoUdf = TRUE;
|
||||
}
|
||||
|
||||
pPos = StrStr(pCmdLine, L"FirstTry=@");
|
||||
if (pPos)
|
||||
@ -544,8 +791,20 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
|
||||
}
|
||||
|
||||
pGrubParam = (ventoy_grub_param *)StrHexToUintn(pPos + StrLen(L"env_param="));
|
||||
grub_env_set = pGrubParam->grub_env_set;
|
||||
grub_env_get = pGrubParam->grub_env_get;
|
||||
pEnv = grub_env_get("VTOY_CHKDEV_RESULT_STRING");
|
||||
if (!pEnv)
|
||||
{
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (pEnv[0] != '0' || pEnv[1] != 0)
|
||||
{
|
||||
ventoy_warn_invalid_device();
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
g_file_replace_list = &pGrubParam->file_replace;
|
||||
old_cnt = g_file_replace_list->old_file_cnt;
|
||||
debug("file replace: magic:0x%x virtid:%u name count:%u <%a> <%a> <%a> <%a>",
|
||||
@ -559,20 +818,33 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
|
||||
);
|
||||
|
||||
pPos = StrStr(pCmdLine, L"mem:");
|
||||
g_chain = (ventoy_chain_head *)StrHexToUintn(pPos + 4);
|
||||
chain = (ventoy_chain_head *)StrHexToUintn(pPos + 4);
|
||||
|
||||
pPos = StrStr(pPos, L"size:");
|
||||
size = StrDecimalToUintn(pPos + 5);
|
||||
|
||||
debug("memory addr:%p size:%lu", g_chain, size);
|
||||
debug("memory addr:%p size:%lu", chain, size);
|
||||
|
||||
if (StrStr(pCmdLine, L"sector512"))
|
||||
{
|
||||
gSector512Mode = TRUE;
|
||||
}
|
||||
|
||||
if (StrStr(pCmdLine, L"memdisk"))
|
||||
{
|
||||
g_iso_buf_size = size;
|
||||
g_iso_data_buf = (UINT8 *)chain + sizeof(ventoy_chain_head);
|
||||
g_iso_buf_size = size - sizeof(ventoy_chain_head);
|
||||
debug("memdisk mode iso_buf_size:%u", g_iso_buf_size);
|
||||
|
||||
g_chain = chain;
|
||||
gMemdiskMode = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("This is normal mode");
|
||||
g_chain = AllocatePool(size);
|
||||
CopyMem(g_chain, chain, size);
|
||||
|
||||
g_chunk = (ventoy_img_chunk *)((char *)g_chain + g_chain->img_chunk_offset);
|
||||
g_img_chunk_num = g_chain->img_chunk_num;
|
||||
g_override_chunk = (ventoy_override_chunk *)((char *)g_chain + g_chain->override_chunk_offset);
|
||||
@ -583,12 +855,12 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
|
||||
g_os_param_reserved = (UINT8 *)(g_chain->os_param.vtoy_reserved);
|
||||
|
||||
/* Workaround for Windows & ISO9660 */
|
||||
if (g_os_param_reserved[2] == 1 && g_os_param_reserved[3] == 0)
|
||||
if (g_os_param_reserved[2] == ventoy_chain_windows && g_os_param_reserved[3] == 0)
|
||||
{
|
||||
g_fixup_iso9660_secover_enable = TRUE;
|
||||
}
|
||||
|
||||
if (g_os_param_reserved[2] == 1 && g_os_param_reserved[4] != 1)
|
||||
if (g_os_param_reserved[2] == ventoy_chain_windows && g_os_param_reserved[4] != 1)
|
||||
{
|
||||
g_hook_keyboard = TRUE;
|
||||
}
|
||||
@ -613,6 +885,19 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
|
||||
}
|
||||
}
|
||||
|
||||
g_fix_windows_1st_cdrom_issue = FALSE;
|
||||
if (ventoy_chain_windows == g_os_param_reserved[2] ||
|
||||
ventoy_chain_wim == g_os_param_reserved[2])
|
||||
{
|
||||
if (ventoy_is_cdrom_dp_exist())
|
||||
{
|
||||
debug("fixup the 1st cdrom influences when boot windows ...");
|
||||
g_fix_windows_1st_cdrom_issue = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
ventoy_debug_pause();
|
||||
|
||||
FreePool(pCmdLine);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
@ -622,6 +907,11 @@ EFI_STATUS EFIAPI ventoy_clean_env(VOID)
|
||||
FreePool(g_sector_flag);
|
||||
g_sector_flag_num = 0;
|
||||
|
||||
if (gLoadIsoEfi && gBlockData.IsoDriverImage)
|
||||
{
|
||||
gBS->UnloadImage(gBlockData.IsoDriverImage);
|
||||
}
|
||||
|
||||
gBS->DisconnectController(gBlockData.Handle, NULL, NULL);
|
||||
|
||||
gBS->UninstallMultipleProtocolInterfaces(gBlockData.Handle,
|
||||
@ -631,9 +921,50 @@ EFI_STATUS EFIAPI ventoy_clean_env(VOID)
|
||||
|
||||
ventoy_delete_variable();
|
||||
|
||||
if (g_chain->os_param.vtoy_img_location_addr)
|
||||
if (g_vtoy_img_location_buf)
|
||||
{
|
||||
FreePool((VOID *)(UINTN)g_chain->os_param.vtoy_img_location_addr);
|
||||
FreePool(g_vtoy_img_location_buf);
|
||||
}
|
||||
|
||||
if (!gMemdiskMode)
|
||||
{
|
||||
FreePool(g_chain);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
STATIC EFI_STATUS ventoy_hook_start(VOID)
|
||||
{
|
||||
/* don't add debug print in this function */
|
||||
|
||||
if (g_fix_windows_1st_cdrom_issue)
|
||||
{
|
||||
ventoy_hook_1st_cdrom_start();
|
||||
}
|
||||
|
||||
/* let this the last */
|
||||
if (g_hook_keyboard)
|
||||
{
|
||||
ventoy_hook_keyboard_start();
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
STATIC EFI_STATUS ventoy_hook_stop(VOID)
|
||||
{
|
||||
/* don't add debug print in this function */
|
||||
|
||||
if (g_fix_windows_1st_cdrom_issue)
|
||||
{
|
||||
ventoy_hook_1st_cdrom_stop();
|
||||
}
|
||||
|
||||
/* let this the last */
|
||||
if (g_hook_keyboard)
|
||||
{
|
||||
ventoy_hook_keyboard_stop();
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
@ -725,17 +1056,11 @@ EFI_STATUS EFIAPI ventoy_boot(IN EFI_HANDLE ImageHandle)
|
||||
pFile->OpenVolume = ventoy_wrapper_open_volume;
|
||||
}
|
||||
|
||||
if (g_hook_keyboard)
|
||||
{
|
||||
ventoy_hook_keyboard_start();
|
||||
}
|
||||
ventoy_hook_start();
|
||||
/* can't add debug print here */
|
||||
//ventoy_wrapper_system();
|
||||
Status = gBS->StartImage(Image, NULL, NULL);
|
||||
if (g_hook_keyboard)
|
||||
{
|
||||
ventoy_hook_keyboard_stop();
|
||||
}
|
||||
ventoy_hook_stop();
|
||||
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
@ -750,8 +1075,13 @@ EFI_STATUS EFIAPI ventoy_boot(IN EFI_HANDLE ImageHandle)
|
||||
|
||||
if (Find == 0)
|
||||
{
|
||||
if (gDotEfiBoot)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
debug("Fs not found, now wait and retry...");
|
||||
sleep(2);
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -789,46 +1119,90 @@ EFI_STATUS EFIAPI VentoyEfiMain
|
||||
gST->ConOut->ClearScreen(gST->ConOut);
|
||||
ventoy_clear_input();
|
||||
|
||||
ventoy_parse_cmdline(ImageHandle);
|
||||
Status = ventoy_parse_cmdline(ImageHandle);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
ventoy_disable_ex_filesystem();
|
||||
|
||||
if (gMemdiskMode)
|
||||
{
|
||||
g_ramdisk_param.PhyAddr = (UINT64)(UINTN)g_chain;
|
||||
g_ramdisk_param.PhyAddr = (UINT64)(UINTN)g_iso_data_buf;
|
||||
g_ramdisk_param.DiskSize = (UINT64)g_iso_buf_size;
|
||||
|
||||
ventoy_save_ramdisk_param();
|
||||
|
||||
if (gLoadIsoEfi)
|
||||
{
|
||||
ventoy_find_iso_disk(ImageHandle);
|
||||
ventoy_find_iso_disk_fs(ImageHandle);
|
||||
ventoy_load_isoefi_driver(ImageHandle);
|
||||
}
|
||||
|
||||
ventoy_install_blockio(ImageHandle, g_iso_buf_size);
|
||||
ventoy_debug_pause();
|
||||
|
||||
Status = ventoy_boot(ImageHandle);
|
||||
|
||||
ventoy_delete_ramdisk_param();
|
||||
|
||||
if (gLoadIsoEfi && gBlockData.IsoDriverImage)
|
||||
{
|
||||
gBS->UnloadImage(gBlockData.IsoDriverImage);
|
||||
}
|
||||
|
||||
gBS->DisconnectController(gBlockData.Handle, NULL, NULL);
|
||||
gBS->UninstallMultipleProtocolInterfaces(gBlockData.Handle,
|
||||
&gEfiBlockIoProtocolGuid, &gBlockData.BlockIo,
|
||||
&gEfiDevicePathProtocolGuid, gBlockData.Path,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
ventoy_save_variable();
|
||||
ventoy_find_iso_disk(ImageHandle);
|
||||
Status = ventoy_find_iso_disk(ImageHandle);
|
||||
if (!EFI_ERROR(Status))
|
||||
{
|
||||
if (gLoadIsoEfi)
|
||||
{
|
||||
ventoy_find_iso_disk_fs(ImageHandle);
|
||||
ventoy_load_isoefi_driver(ImageHandle);
|
||||
}
|
||||
|
||||
ventoy_debug_pause();
|
||||
ventoy_debug_pause();
|
||||
|
||||
ventoy_install_blockio(ImageHandle, g_chain->virt_img_size_in_bytes);
|
||||
|
||||
ventoy_debug_pause();
|
||||
|
||||
Status = ventoy_boot(ImageHandle);
|
||||
}
|
||||
|
||||
ventoy_install_blockio(ImageHandle, g_chain->virt_img_size_in_bytes);
|
||||
|
||||
ventoy_debug_pause();
|
||||
|
||||
Status = ventoy_boot(ImageHandle);
|
||||
|
||||
ventoy_clean_env();
|
||||
}
|
||||
|
||||
if (EFI_NOT_FOUND == Status)
|
||||
if (FALSE == gDotEfiBoot && FALSE == gBootFallBack)
|
||||
{
|
||||
gST->ConOut->OutputString(gST->ConOut, L"No bootfile found for UEFI!\r\n");
|
||||
gST->ConOut->OutputString(gST->ConOut, L"Maybe the image does not support " VENTOY_UEFI_DESC L"!\r\n");
|
||||
sleep(30);
|
||||
if (EFI_NOT_FOUND == Status)
|
||||
{
|
||||
gST->ConOut->OutputString(gST->ConOut, L"No bootfile found for UEFI!\r\n");
|
||||
gST->ConOut->OutputString(gST->ConOut, L"Maybe the image does not support " VENTOY_UEFI_DESC L"!\r\n");
|
||||
sleep(30);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ventoy_clear_input();
|
||||
gST->ConOut->ClearScreen(gST->ConOut);
|
||||
|
||||
if (gDotEfiBoot && (EFI_NOT_FOUND == Status))
|
||||
{
|
||||
grub_env_set("vtoy_dotefi_retry", "YES");
|
||||
}
|
||||
|
||||
ventoy_enable_ex_filesystem();
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,15 @@
|
||||
|
||||
#define VENTOY_GUID { 0x77772020, 0x2e77, 0x6576, { 0x6e, 0x74, 0x6f, 0x79, 0x2e, 0x6e, 0x65, 0x74 }}
|
||||
|
||||
typedef enum ventoy_chain_type
|
||||
{
|
||||
ventoy_chain_linux = 0, /* 0: linux */
|
||||
ventoy_chain_windows, /* 1: windows */
|
||||
ventoy_chain_wim, /* 2: wim */
|
||||
|
||||
ventoy_chain_max
|
||||
}ventoy_chain_type;
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
typedef struct ventoy_guid
|
||||
@ -159,21 +168,32 @@ typedef struct ventoy_virt_chunk
|
||||
#define VTOY_BLOCK_DEVICE_PATH_GUID \
|
||||
{ 0x37b87ac6, 0xc180, 0x4583, { 0xa7, 0x05, 0x41, 0x4d, 0xa8, 0xf7, 0x7e, 0xd2 }}
|
||||
|
||||
#define VTOY_BLOCK_DEVICE_PATH_NAME L"ventoy"
|
||||
|
||||
|
||||
#if defined (MDE_CPU_IA32)
|
||||
#define VENTOY_UEFI_DESC L"IA32 UEFI"
|
||||
#define ISO9660_EFI_DRIVER_PATH L"\\ventoy\\iso9660_ia32.efi"
|
||||
#define UDF_EFI_DRIVER_PATH L"\\ventoy\\udf_ia32.efi"
|
||||
#elif defined (MDE_CPU_X64)
|
||||
#define VENTOY_UEFI_DESC L"X64 UEFI"
|
||||
#define ISO9660_EFI_DRIVER_PATH L"\\ventoy\\iso9660_x64.efi"
|
||||
#define UDF_EFI_DRIVER_PATH L"\\ventoy\\udf_x64.efi"
|
||||
#elif defined (MDE_CPU_EBC)
|
||||
#elif defined (MDE_CPU_ARM)
|
||||
#define VENTOY_UEFI_DESC L"ARM UEFI"
|
||||
#define ISO9660_EFI_DRIVER_PATH L"\\ventoy\\iso9660_arm.efi"
|
||||
#define UDF_EFI_DRIVER_PATH L"\\ventoy\\udf_arm.efi"
|
||||
#elif defined (MDE_CPU_AARCH64)
|
||||
#define VENTOY_UEFI_DESC L"ARM64 UEFI"
|
||||
#define ISO9660_EFI_DRIVER_PATH L"\\ventoy\\iso9660_aa64.efi"
|
||||
#define UDF_EFI_DRIVER_PATH L"\\ventoy\\udf_aa64.efi"
|
||||
#else
|
||||
#error Unknown Processor Type
|
||||
#endif
|
||||
|
||||
#define VENTOY_DEVICE_WARN 1
|
||||
#define VTOY_WARNING L"!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!"
|
||||
|
||||
typedef struct ventoy_sector_flag
|
||||
{
|
||||
UINT8 flag; // 0:init 1:mem 2:remap
|
||||
@ -199,6 +219,7 @@ typedef struct vtoy_block_data
|
||||
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *pDiskFs;
|
||||
EFI_DEVICE_PATH_PROTOCOL *pDiskFsDevPath;
|
||||
|
||||
EFI_HANDLE IsoDriverImage;
|
||||
}vtoy_block_data;
|
||||
|
||||
|
||||
@ -215,7 +236,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)
|
||||
|
||||
@ -242,8 +265,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
|
||||
@ -260,6 +284,32 @@ typedef struct ventoy_iso9660_override
|
||||
UINT32 size_be;
|
||||
}ventoy_iso9660_override;
|
||||
|
||||
typedef struct PART_TABLE
|
||||
{
|
||||
UINT8 Active; // 0x00 0x80
|
||||
|
||||
UINT8 StartHead;
|
||||
UINT16 StartSector : 6;
|
||||
UINT16 StartCylinder : 10;
|
||||
|
||||
UINT8 FsFlag;
|
||||
|
||||
UINT8 EndHead;
|
||||
UINT16 EndSector : 6;
|
||||
UINT16 EndCylinder : 10;
|
||||
|
||||
UINT32 StartSectorId;
|
||||
UINT32 SectorCount;
|
||||
}PART_TABLE;
|
||||
|
||||
typedef struct MBR_HEAD
|
||||
{
|
||||
UINT8 BootCode[446];
|
||||
PART_TABLE PartTbl[4];
|
||||
UINT8 Byte55;
|
||||
UINT8 ByteAA;
|
||||
}MBR_HEAD;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
|
||||
@ -279,8 +329,28 @@ 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 MAX_DRIVER_BIND_WRAPPER 64
|
||||
typedef struct DriverBindWrapper
|
||||
{
|
||||
EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
|
||||
EFI_DRIVER_BINDING_SUPPORTED pfOldSupport;
|
||||
}DRIVER_BIND_WRAPPER;
|
||||
|
||||
#define ventoy_wrapper(bs, wrapper, func, newfunc) \
|
||||
{\
|
||||
wrapper.Ori##func = bs->func;\
|
||||
@ -288,6 +358,22 @@ typedef struct ventoy_system_wrapper
|
||||
bs->func = wrapper.New##func;\
|
||||
}
|
||||
|
||||
|
||||
#define VENTOY_GET_COMPONENT_NAME(Protocol, DriverName) \
|
||||
{\
|
||||
DriverName = NULL;\
|
||||
Status = Protocol->GetDriverName(Protocol, "en", &DriverName);\
|
||||
if (EFI_ERROR(Status) || NULL == DriverName) \
|
||||
{\
|
||||
DriverName = NULL;\
|
||||
Status = Protocol->GetDriverName(Protocol, "eng", &DriverName);\
|
||||
if (EFI_ERROR(Status) || NULL == DriverName) \
|
||||
{\
|
||||
continue;\
|
||||
}\
|
||||
}\
|
||||
}
|
||||
|
||||
extern BOOLEAN gDebugPrint;
|
||||
VOID EFIAPI VtoyDebug(IN CONST CHAR8 *Format, ...);
|
||||
EFI_STATUS EFIAPI ventoy_wrapper_system(VOID);
|
||||
@ -313,10 +399,13 @@ 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
|
||||
(
|
||||
@ -327,6 +416,11 @@ EFI_STATUS EFIAPI ventoy_install_blockio(IN EFI_HANDLE ImageHandle, IN UINT64 Im
|
||||
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);
|
||||
EFI_STATUS ventoy_disable_ex_filesystem(VOID);
|
||||
EFI_STATUS ventoy_enable_ex_filesystem(VOID);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -1,81 +1,81 @@
|
||||
#************************************************************************************
|
||||
# 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 = Ventoy
|
||||
FILE_GUID = 1c3a0915-09dc-49c2-873d-0aaaa7733299
|
||||
MODULE_TYPE = UEFI_APPLICATION
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = VentoyEfiMain
|
||||
|
||||
|
||||
[Sources]
|
||||
Ventoy.h
|
||||
Ventoy.c
|
||||
VentoyDebug.c
|
||||
VentoyProtocol.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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#************************************************************************************
|
||||
# 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 = Ventoy
|
||||
FILE_GUID = 1c3a0915-09dc-49c2-873d-0aaaa7733299
|
||||
MODULE_TYPE = UEFI_APPLICATION
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = VentoyEfiMain
|
||||
|
||||
|
||||
[Sources]
|
||||
Ventoy.h
|
||||
Ventoy.c
|
||||
VentoyDebug.c
|
||||
VentoyProtocol.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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -34,11 +34,12 @@
|
||||
#include <Protocol/BlockIo.h>
|
||||
#include <Protocol/RamDisk.h>
|
||||
#include <Protocol/SimpleFileSystem.h>
|
||||
#include <Protocol/DriverBinding.h>
|
||||
#include <Ventoy.h>
|
||||
|
||||
#define PROCOTOL_SLEEP_SECONDS 0
|
||||
#define PROCOTOL_SLEEP_MSECONDS 0
|
||||
|
||||
#define debug_sleep() if (PROCOTOL_SLEEP_SECONDS) sleep(PROCOTOL_SLEEP_SECONDS)
|
||||
#define debug_sleep() if (PROCOTOL_SLEEP_MSECONDS) gBS->Stall(1000 * PROCOTOL_SLEEP_MSECONDS)
|
||||
|
||||
STATIC ventoy_system_wrapper g_system_wrapper;
|
||||
|
||||
@ -126,7 +127,7 @@ STATIC EFI_STATUS EFIAPI ventoy_open_protocol
|
||||
IN UINT32 Attributes
|
||||
)
|
||||
{
|
||||
debug("ventoy_open_protocol:%a", ventoy_get_guid_name(Protocol)); debug_sleep();
|
||||
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);
|
||||
}
|
||||
|
||||
@ -141,11 +142,87 @@ STATIC EFI_STATUS EFIAPI ventoy_locate_protocol
|
||||
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;
|
||||
}
|
||||
|
@ -34,10 +34,13 @@
|
||||
#include <Protocol/BlockIo.h>
|
||||
#include <Protocol/RamDisk.h>
|
||||
#include <Protocol/SimpleFileSystem.h>
|
||||
#include <Protocol/DriverBinding.h>
|
||||
#include <Ventoy.h>
|
||||
|
||||
UINT8 *g_iso_data_buf = NULL;
|
||||
UINTN g_iso_buf_size = 0;
|
||||
BOOLEAN gMemdiskMode = FALSE;
|
||||
BOOLEAN gSector512Mode = FALSE;
|
||||
|
||||
ventoy_sector_flag *g_sector_flag = NULL;
|
||||
UINT32 g_sector_flag_num = 0;
|
||||
@ -65,6 +68,54 @@ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *g_con_simple_input_ex = NULL;
|
||||
STATIC EFI_INPUT_READ_KEY_EX g_org_read_key_ex = NULL;
|
||||
STATIC EFI_INPUT_READ_KEY g_org_read_key = NULL;
|
||||
|
||||
STATIC EFI_LOCATE_HANDLE g_org_locate_handle = NULL;
|
||||
|
||||
STATIC UINT8 g_sector_buf[2048];
|
||||
STATIC EFI_BLOCK_READ g_sector_2048_read = NULL;
|
||||
STATIC EFI_BLOCK_WRITE g_sector_2048_write = NULL;
|
||||
|
||||
STATIC UINTN g_DriverBindWrapperCnt = 0;
|
||||
STATIC DRIVER_BIND_WRAPPER g_DriverBindWrapperList[MAX_DRIVER_BIND_WRAPPER];
|
||||
|
||||
BOOLEAN ventoy_is_cdrom_dp_exist(VOID)
|
||||
{
|
||||
UINTN i = 0;
|
||||
UINTN Count = 0;
|
||||
EFI_HANDLE *Handles = NULL;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_DEVICE_PATH_PROTOCOL *DevicePath = NULL;
|
||||
|
||||
Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiDevicePathProtocolGuid,
|
||||
NULL, &Count, &Handles);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (i = 0; i < Count; i++)
|
||||
{
|
||||
Status = gBS->HandleProtocol(Handles[i], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePath);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
while (!IsDevicePathEnd(DevicePath))
|
||||
{
|
||||
if (MEDIA_DEVICE_PATH == DevicePath->Type && MEDIA_CDROM_DP == DevicePath->SubType)
|
||||
{
|
||||
FreePool(Handles);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
DevicePath = NextDevicePathNode(DevicePath);
|
||||
}
|
||||
}
|
||||
|
||||
FreePool(Handles);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Block IO procotol */
|
||||
#endif
|
||||
@ -101,7 +152,7 @@ STATIC EFI_STATUS EFIAPI ventoy_read_iso_sector
|
||||
ventoy_override_chunk *pOverride = g_override_chunk;
|
||||
EFI_BLOCK_IO_PROTOCOL *pRawBlockIo = gBlockData.pRawBlockIo;
|
||||
|
||||
debug("read iso sector %lu count %u", Sector, Count);
|
||||
debug("read iso sector %lu count %u Buffer:%p Align:%u", Sector, Count, Buffer, pRawBlockIo->Media->IoAlign);
|
||||
|
||||
ReadStart = Sector * 2048;
|
||||
ReadEnd = (Sector + Count) * 2048;
|
||||
@ -114,9 +165,17 @@ STATIC EFI_STATUS EFIAPI ventoy_read_iso_sector
|
||||
{
|
||||
MapLba = (Sector - pchunk->img_start_sector) * 4 + pchunk->disk_start_sector;
|
||||
}
|
||||
else
|
||||
else if (g_chain->disk_sector_size == 1024)
|
||||
{
|
||||
MapLba = (Sector - pchunk->img_start_sector) * 2048 / g_chain->disk_sector_size + pchunk->disk_start_sector;
|
||||
MapLba = (Sector - pchunk->img_start_sector) * 2 + pchunk->disk_start_sector;
|
||||
}
|
||||
else if (g_chain->disk_sector_size == 2048)
|
||||
{
|
||||
MapLba = (Sector - pchunk->img_start_sector) + pchunk->disk_start_sector;
|
||||
}
|
||||
else if (g_chain->disk_sector_size == 4096)
|
||||
{
|
||||
MapLba = ((Sector - pchunk->img_start_sector) >> 1) + pchunk->disk_start_sector;
|
||||
}
|
||||
|
||||
secLeft = pchunk->img_end_sector + 1 - Sector;
|
||||
@ -126,7 +185,7 @@ STATIC EFI_STATUS EFIAPI ventoy_read_iso_sector
|
||||
MapLba, secRead * 2048, pCurBuf);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
debug("Raw disk read block failed %r", Status);
|
||||
debug("Raw disk read block failed %r LBA:%lu Count:%u %p", Status, MapLba, secRead, pCurBuf);
|
||||
return Status;
|
||||
}
|
||||
|
||||
@ -199,6 +258,96 @@ STATIC EFI_STATUS EFIAPI ventoy_read_iso_sector
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
STATIC EFI_STATUS EFIAPI ventoy_write_iso_sector
|
||||
(
|
||||
IN UINT64 Sector,
|
||||
IN UINTN Count,
|
||||
IN VOID *Buffer
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_LBA MapLba = 0;
|
||||
UINT32 i = 0;
|
||||
UINTN secLeft = 0;
|
||||
UINTN secRead = 0;
|
||||
UINT64 ReadStart = 0;
|
||||
UINT64 ReadEnd = 0;
|
||||
UINT8 *pCurBuf = (UINT8 *)Buffer;
|
||||
ventoy_img_chunk *pchunk = g_chunk;
|
||||
EFI_BLOCK_IO_PROTOCOL *pRawBlockIo = gBlockData.pRawBlockIo;
|
||||
|
||||
debug("write iso sector %lu count %u", Sector, Count);
|
||||
|
||||
ReadStart = Sector * 2048;
|
||||
ReadEnd = (Sector + Count) * 2048;
|
||||
|
||||
for (i = 0; Count > 0 && i < g_img_chunk_num; i++, pchunk++)
|
||||
{
|
||||
if (Sector >= pchunk->img_start_sector && Sector <= pchunk->img_end_sector)
|
||||
{
|
||||
if (g_chain->disk_sector_size == 512)
|
||||
{
|
||||
MapLba = (Sector - pchunk->img_start_sector) * 4 + pchunk->disk_start_sector;
|
||||
}
|
||||
else if (g_chain->disk_sector_size == 1024)
|
||||
{
|
||||
MapLba = (Sector - pchunk->img_start_sector) * 2 + pchunk->disk_start_sector;
|
||||
}
|
||||
else if (g_chain->disk_sector_size == 2048)
|
||||
{
|
||||
MapLba = (Sector - pchunk->img_start_sector) + pchunk->disk_start_sector;
|
||||
}
|
||||
else if (g_chain->disk_sector_size == 4096)
|
||||
{
|
||||
MapLba = ((Sector - pchunk->img_start_sector) >> 1) + pchunk->disk_start_sector;
|
||||
}
|
||||
|
||||
|
||||
secLeft = pchunk->img_end_sector + 1 - Sector;
|
||||
secRead = (Count < secLeft) ? Count : secLeft;
|
||||
|
||||
Status = pRawBlockIo->WriteBlocks(pRawBlockIo, pRawBlockIo->Media->MediaId,
|
||||
MapLba, secRead * 2048, pCurBuf);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
debug("Raw disk write block failed %r LBA:%lu Count:%u", Status, MapLba, secRead);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Count -= secRead;
|
||||
Sector += secRead;
|
||||
pCurBuf += secRead * 2048;
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_block_io_ramdisk_write
|
||||
(
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSize,
|
||||
IN VOID *Buffer
|
||||
)
|
||||
{
|
||||
(VOID)This;
|
||||
(VOID)MediaId;
|
||||
(VOID)Lba;
|
||||
(VOID)BufferSize;
|
||||
(VOID)Buffer;
|
||||
|
||||
if (!gSector512Mode)
|
||||
{
|
||||
return EFI_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
CopyMem(g_iso_data_buf + (Lba * 2048), Buffer, BufferSize);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_block_io_ramdisk_read
|
||||
(
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
@ -213,7 +362,7 @@ EFI_STATUS EFIAPI ventoy_block_io_ramdisk_read
|
||||
(VOID)This;
|
||||
(VOID)MediaId;
|
||||
|
||||
CopyMem(Buffer, (char *)g_chain + (Lba * 2048), BufferSize);
|
||||
CopyMem(Buffer, g_iso_data_buf + (Lba * 2048), BufferSize);
|
||||
|
||||
if (g_blockio_start_record_bcd && FALSE == g_blockio_bcd_read_done)
|
||||
{
|
||||
@ -279,7 +428,7 @@ end:
|
||||
return Lba;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_block_io_read
|
||||
EFI_STATUS EFIAPI ventoy_block_io_read_real
|
||||
(
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
@ -292,6 +441,8 @@ EFI_STATUS EFIAPI ventoy_block_io_read
|
||||
UINT32 j = 0;
|
||||
UINT32 lbacount = 0;
|
||||
UINT32 secNum = 0;
|
||||
UINT32 TmpNum = 0;
|
||||
UINT64 VirtSec = 0;
|
||||
UINT64 offset = 0;
|
||||
EFI_LBA curlba = 0;
|
||||
EFI_LBA lastlba = 0;
|
||||
@ -299,7 +450,7 @@ EFI_STATUS EFIAPI ventoy_block_io_read
|
||||
ventoy_sector_flag *cur_flag;
|
||||
ventoy_virt_chunk *node;
|
||||
|
||||
//debug("### ventoy_block_io_read sector:%u count:%u", (UINT32)Lba, (UINT32)BufferSize / 2048);
|
||||
debug("### block_io_read_real sector:%u count:%u Buffer:%p", (UINT32)Lba, (UINT32)BufferSize / 2048, Buffer);
|
||||
|
||||
secNum = BufferSize / 2048;
|
||||
|
||||
@ -315,6 +466,28 @@ EFI_STATUS EFIAPI ventoy_block_io_read
|
||||
{
|
||||
return ventoy_read_iso_sector(Lba, secNum, Buffer);
|
||||
}
|
||||
else if (offset < g_chain->real_img_size_in_bytes)
|
||||
{
|
||||
TmpNum = (g_chain->real_img_size_in_bytes - offset) / 2048;
|
||||
ventoy_read_iso_sector(Lba, TmpNum, Buffer);
|
||||
|
||||
Lba += TmpNum;
|
||||
secNum -= TmpNum;
|
||||
Buffer = (UINT8 *)Buffer + (g_chain->real_img_size_in_bytes - offset);
|
||||
offset = Lba * 2048;
|
||||
}
|
||||
|
||||
VirtSec = g_chain->virt_img_size_in_bytes / 2048;
|
||||
if (Lba >= VirtSec)
|
||||
{
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
else if (Lba + secNum > VirtSec)
|
||||
{
|
||||
secNum = VirtSec - Lba;
|
||||
}
|
||||
|
||||
debug("XXX block_io_read_real sector:%u count:%u Buffer:%p", (UINT32)Lba, (UINT32)BufferSize / 2048, Buffer);
|
||||
|
||||
if (secNum > g_sector_flag_num)
|
||||
{
|
||||
@ -383,6 +556,42 @@ EFI_STATUS EFIAPI ventoy_block_io_read
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_block_io_read
|
||||
(
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSize,
|
||||
OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
UINT32 IoAlign = 0;
|
||||
VOID *NewBuf = NULL;
|
||||
EFI_STATUS Status = EFI_OUT_OF_RESOURCES;
|
||||
|
||||
if (gBlockData.pRawBlockIo && gBlockData.pRawBlockIo->Media)
|
||||
{
|
||||
IoAlign = gBlockData.pRawBlockIo->Media->IoAlign;
|
||||
}
|
||||
|
||||
if ((IoAlign == 0) || (((UINTN) Buffer & (IoAlign - 1)) == 0))
|
||||
{
|
||||
Status = ventoy_block_io_read_real(This, MediaId, Lba, BufferSize, Buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
NewBuf = AllocatePages(EFI_SIZE_TO_PAGES(BufferSize + IoAlign));
|
||||
if (NewBuf)
|
||||
{
|
||||
Status = ventoy_block_io_read_real(This, MediaId, Lba, BufferSize, NewBuf);
|
||||
CopyMem(Buffer, NewBuf, BufferSize);
|
||||
FreePages(NewBuf, EFI_SIZE_TO_PAGES(BufferSize + IoAlign));
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_block_io_write
|
||||
(
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
@ -392,12 +601,21 @@ EFI_STATUS EFIAPI ventoy_block_io_write
|
||||
IN VOID *Buffer
|
||||
)
|
||||
{
|
||||
UINT32 secNum = 0;
|
||||
UINT64 offset = 0;
|
||||
|
||||
(VOID)This;
|
||||
(VOID)MediaId;
|
||||
(VOID)Lba;
|
||||
(VOID)BufferSize;
|
||||
(VOID)Buffer;
|
||||
return EFI_WRITE_PROTECTED;
|
||||
|
||||
if (!gSector512Mode)
|
||||
{
|
||||
return EFI_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
secNum = BufferSize / 2048;
|
||||
offset = Lba * 2048;
|
||||
|
||||
return ventoy_write_iso_sector(Lba, secNum, Buffer);
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_block_io_flush(IN EFI_BLOCK_IO_PROTOCOL *This)
|
||||
@ -406,26 +624,74 @@ EFI_STATUS EFIAPI ventoy_block_io_flush(IN EFI_BLOCK_IO_PROTOCOL *This)
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
STATIC UINTN ventoy_get_current_device_path_id(VOID)
|
||||
{
|
||||
UINTN i = 0;
|
||||
UINTN Count = 0;
|
||||
UINTN MaxId = 0;
|
||||
UINTN CurId = 0;
|
||||
BOOLEAN Find = FALSE;
|
||||
EFI_HANDLE *Handles = NULL;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_DEVICE_PATH_PROTOCOL *DevicePath = NULL;
|
||||
VENDOR_DEVICE_PATH *venPath = NULL;
|
||||
|
||||
Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiDevicePathProtocolGuid,
|
||||
NULL, &Count, &Handles);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < Count; i++)
|
||||
{
|
||||
Status = gBS->HandleProtocol(Handles[i], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePath);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (DevicePath->Type == HARDWARE_DEVICE_PATH && DevicePath->SubType == HW_VENDOR_DP)
|
||||
{
|
||||
venPath = (VENDOR_DEVICE_PATH *)DevicePath;
|
||||
if (CompareGuid(&venPath->Guid, &gVtoyBlockDevicePathGuid))
|
||||
{
|
||||
CurId = StrDecimalToUintn((CHAR16 *)(venPath + 1) + StrLen(L"ventoy_"));
|
||||
MaxId = MAX(MaxId, CurId);
|
||||
Find = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FreePool(Handles);
|
||||
|
||||
return Find ? (MaxId + 1) : 0;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_fill_device_path(VOID)
|
||||
{
|
||||
UINTN CurVtoyDpId = 0;
|
||||
UINTN NameLen = 0;
|
||||
UINT8 TmpBuf[128] = {0};
|
||||
VENDOR_DEVICE_PATH *venPath = NULL;
|
||||
CHAR16 VtoyDpName[32];
|
||||
|
||||
CurVtoyDpId = ventoy_get_current_device_path_id();
|
||||
UnicodeSPrintAsciiFormat(VtoyDpName, sizeof(VtoyDpName), "ventoy_%03lu", CurVtoyDpId);
|
||||
|
||||
venPath = (VENDOR_DEVICE_PATH *)TmpBuf;
|
||||
NameLen = StrSize(VTOY_BLOCK_DEVICE_PATH_NAME);
|
||||
NameLen = StrSize(VtoyDpName);
|
||||
venPath->Header.Type = HARDWARE_DEVICE_PATH;
|
||||
venPath->Header.SubType = HW_VENDOR_DP;
|
||||
venPath->Header.Length[0] = sizeof(VENDOR_DEVICE_PATH) + NameLen;
|
||||
venPath->Header.Length[1] = 0;
|
||||
CopyMem(&venPath->Guid, &gVtoyBlockDevicePathGuid, sizeof(EFI_GUID));
|
||||
CopyMem(venPath + 1, VTOY_BLOCK_DEVICE_PATH_NAME, NameLen);
|
||||
CopyMem(venPath + 1, VtoyDpName, NameLen);
|
||||
|
||||
gBlockData.Path = AppendDevicePathNode(NULL, (EFI_DEVICE_PATH_PROTOCOL *)TmpBuf);
|
||||
gBlockData.DevicePathCompareLen = sizeof(VENDOR_DEVICE_PATH) + NameLen;
|
||||
|
||||
debug("gBlockData.Path=<%s>\n", ConvertDevicePathToText(gBlockData.Path, FALSE, FALSE));
|
||||
debug("gBlockData.Path=<%lu><%s>\n", CurVtoyDpId, ConvertDevicePathToText(gBlockData.Path, FALSE, FALSE));
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
@ -458,11 +724,7 @@ EFI_STATUS EFIAPI ventoy_connect_driver(IN EFI_HANDLE ControllerHandle, IN CONST
|
||||
continue;
|
||||
}
|
||||
|
||||
Status = Name2Protocol->GetDriverName(Name2Protocol, "en", &DriverName);
|
||||
if (EFI_ERROR(Status) || NULL == DriverName)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
VENTOY_GET_COMPONENT_NAME(Name2Protocol, DriverName);
|
||||
|
||||
if (StrStr(DriverName, DrvName))
|
||||
{
|
||||
@ -475,7 +737,7 @@ EFI_STATUS EFIAPI ventoy_connect_driver(IN EFI_HANDLE ControllerHandle, IN CONST
|
||||
if (i < Count)
|
||||
{
|
||||
Status = gBS->ConnectController(ControllerHandle, DrvHandles, NULL, TRUE);
|
||||
debug("Connect partition driver:<%r>", Status);
|
||||
debug("ventoy_connect_driver:<%s> <%r>", DrvName, Status);
|
||||
goto end;
|
||||
}
|
||||
|
||||
@ -500,11 +762,7 @@ EFI_STATUS EFIAPI ventoy_connect_driver(IN EFI_HANDLE ControllerHandle, IN CONST
|
||||
continue;
|
||||
}
|
||||
|
||||
Status = NameProtocol->GetDriverName(NameProtocol, "en", &DriverName);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
VENTOY_GET_COMPONENT_NAME(NameProtocol, DriverName);
|
||||
|
||||
if (StrStr(DriverName, DrvName))
|
||||
{
|
||||
@ -517,7 +775,7 @@ EFI_STATUS EFIAPI ventoy_connect_driver(IN EFI_HANDLE ControllerHandle, IN CONST
|
||||
if (i < Count)
|
||||
{
|
||||
Status = gBS->ConnectController(ControllerHandle, DrvHandles, NULL, TRUE);
|
||||
debug("Connect partition driver:<%r>", Status);
|
||||
debug("ventoy_connect_driver:<%s> <%r>", DrvName, Status);
|
||||
goto end;
|
||||
}
|
||||
|
||||
@ -529,24 +787,386 @@ end:
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
STATIC BOOLEAN ventoy_filesystem_need_wrapper(IN CONST CHAR16 *DrvName)
|
||||
{
|
||||
UINTN i;
|
||||
CHAR16 UpperDrvName[256];
|
||||
|
||||
StrCpyS(UpperDrvName, 256, DrvName);
|
||||
|
||||
for (i = 0; i < 256 && UpperDrvName[i]; i++)
|
||||
{
|
||||
if (UpperDrvName[i] >= 'a' && UpperDrvName[i] <= 'z')
|
||||
{
|
||||
UpperDrvName[i] = 'A' + (UpperDrvName[i] - 'a');
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* suppress some file system drivers
|
||||
* 1. rEFInd File System Driver
|
||||
*
|
||||
*/
|
||||
|
||||
if (StrStr(UpperDrvName, L"REFIND") && StrStr(UpperDrvName, L"FILE SYSTEM"))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
STATIC VOID ventoy_add_filesystem_wrapper
|
||||
(
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *DriverBindProtocol,
|
||||
IN CONST CHAR16 *DriverName
|
||||
)
|
||||
{
|
||||
UINTN j;
|
||||
|
||||
if (g_DriverBindWrapperCnt >= MAX_DRIVER_BIND_WRAPPER)
|
||||
{
|
||||
debug("driver binding wrapper overflow %lu", g_DriverBindWrapperCnt);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ventoy_filesystem_need_wrapper(DriverName))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (j = 0; j < g_DriverBindWrapperCnt; j++)
|
||||
{
|
||||
if (g_DriverBindWrapperList[j].DriverBinding == DriverBindProtocol)
|
||||
{
|
||||
debug("Duplicate driverbinding <%s> %p %lu %lu", DriverName, DriverBindProtocol, j, g_DriverBindWrapperCnt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (j >= g_DriverBindWrapperCnt)
|
||||
{
|
||||
g_DriverBindWrapperList[g_DriverBindWrapperCnt].DriverBinding = DriverBindProtocol;
|
||||
g_DriverBindWrapperList[g_DriverBindWrapperCnt].pfOldSupport = DriverBindProtocol->Supported;
|
||||
g_DriverBindWrapperCnt++;
|
||||
debug("Add driverbinding <%s> %p %lu", DriverName, DriverBindProtocol, g_DriverBindWrapperCnt);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC EFI_STATUS ventoy_find_filesystem_driverbind(VOID)
|
||||
{
|
||||
UINTN i = 0;
|
||||
UINTN Count = 0;
|
||||
CHAR16 *DriverName = NULL;
|
||||
EFI_HANDLE *Handles = NULL;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_COMPONENT_NAME_PROTOCOL *NameProtocol = NULL;
|
||||
EFI_COMPONENT_NAME2_PROTOCOL *Name2Protocol = NULL;
|
||||
EFI_DRIVER_BINDING_PROTOCOL *DriverBindProtocol = NULL;
|
||||
|
||||
debug("ventoy_find_filesystem_driverbind...");
|
||||
|
||||
Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiComponentName2ProtocolGuid,
|
||||
NULL, &Count, &Handles);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
for (i = 0; i < Count; i++)
|
||||
{
|
||||
Status = gBS->HandleProtocol(Handles[i], &gEfiComponentName2ProtocolGuid, (VOID **)&Name2Protocol);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
VENTOY_GET_COMPONENT_NAME(Name2Protocol, DriverName);
|
||||
|
||||
Status = gBS->HandleProtocol(Handles[i], &gEfiDriverBindingProtocolGuid, (VOID **)&DriverBindProtocol);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
debug("### 2 No DriverBind <%s> <%r>", DriverName, Status);
|
||||
continue;
|
||||
}
|
||||
|
||||
ventoy_add_filesystem_wrapper(DriverBindProtocol, DriverName);
|
||||
}
|
||||
|
||||
Count = 0;
|
||||
FreePool(Handles);
|
||||
Handles = NULL;
|
||||
|
||||
Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiComponentNameProtocolGuid,
|
||||
NULL, &Count, &Handles);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
for (i = 0; i < Count; i++)
|
||||
{
|
||||
Status = gBS->HandleProtocol(Handles[i], &gEfiComponentNameProtocolGuid, (VOID **)&NameProtocol);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
VENTOY_GET_COMPONENT_NAME(NameProtocol, DriverName);
|
||||
|
||||
Status = gBS->HandleProtocol(Handles[i], &gEfiDriverBindingProtocolGuid, (VOID **)&DriverBindProtocol);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
debug("### 1 No DriverBind <%s> <%r>", DriverName, Status);
|
||||
continue;
|
||||
}
|
||||
|
||||
ventoy_add_filesystem_wrapper(DriverBindProtocol, DriverName);
|
||||
}
|
||||
|
||||
FreePool(Handles);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
STATIC EFI_STATUS EFIAPI ventoy_wrapper_driver_bind_support
|
||||
(
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
||||
)
|
||||
{
|
||||
UINTN i;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_DEVICE_PATH_PROTOCOL *DevicePath = NULL;
|
||||
EFI_DRIVER_BINDING_SUPPORTED pfOldSupport = NULL;
|
||||
|
||||
for (i = 0; i < g_DriverBindWrapperCnt; i++)
|
||||
{
|
||||
if (g_DriverBindWrapperList[i].DriverBinding == This)
|
||||
{
|
||||
pfOldSupport = g_DriverBindWrapperList[i].pfOldSupport;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
debug("ventoy_wrapper_driver_bind_support %lu %p", i, pfOldSupport);
|
||||
|
||||
if (!pfOldSupport)
|
||||
{
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
Status = gBS->HandleProtocol(ControllerHandle, &gEfiDevicePathProtocolGuid, (VOID **)&DevicePath);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (0 == CompareMem(gBlockData.Path, DevicePath, gBlockData.DevicePathCompareLen))
|
||||
{
|
||||
debug("return EFI_UNSUPPORTED for ventoy");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
out:
|
||||
return pfOldSupport(This, ControllerHandle, RemainingDevicePath);
|
||||
}
|
||||
|
||||
EFI_STATUS ventoy_disable_ex_filesystem(VOID)
|
||||
{
|
||||
UINTN i;
|
||||
|
||||
ventoy_find_filesystem_driverbind();
|
||||
|
||||
for (i = 0; i < g_DriverBindWrapperCnt; i++)
|
||||
{
|
||||
g_DriverBindWrapperList[i].DriverBinding->Supported = ventoy_wrapper_driver_bind_support;
|
||||
}
|
||||
|
||||
debug("Wrapper Ex Driver Binding %lu", g_DriverBindWrapperCnt);
|
||||
ventoy_debug_pause();
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS ventoy_enable_ex_filesystem(VOID)
|
||||
{
|
||||
UINTN i;
|
||||
|
||||
for (i = 0; i < g_DriverBindWrapperCnt; i++)
|
||||
{
|
||||
g_DriverBindWrapperList[i].DriverBinding->Supported = g_DriverBindWrapperList[i].pfOldSupport;
|
||||
}
|
||||
g_DriverBindWrapperCnt = 0;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_block_io_read_512
|
||||
(
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSize,
|
||||
OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
EFI_LBA Mod;
|
||||
UINTN ReadSize;
|
||||
UINT8 *CurBuf = NULL;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
|
||||
debug("ventoy_block_io_read_512 %lu %lu Buffer:%p\n", Lba, BufferSize / 512, Buffer);
|
||||
|
||||
CurBuf = (UINT8 *)Buffer;
|
||||
|
||||
Mod = Lba % 4;
|
||||
if (Mod > 0)
|
||||
{
|
||||
Status |= g_sector_2048_read(This, MediaId, Lba / 4, 2048, g_sector_buf);
|
||||
|
||||
if (BufferSize <= (4 - Mod) * 512)
|
||||
{
|
||||
CopyMem(CurBuf, g_sector_buf + Mod * 512, BufferSize);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
ReadSize = (4 - Mod) * 512;
|
||||
CopyMem(CurBuf, g_sector_buf + Mod * 512, ReadSize);
|
||||
CurBuf += ReadSize;
|
||||
Lba += (4 - Mod);
|
||||
BufferSize -= ReadSize;
|
||||
}
|
||||
}
|
||||
|
||||
if (BufferSize >= 2048)
|
||||
{
|
||||
ReadSize = BufferSize / 2048 * 2048;
|
||||
|
||||
Status |= g_sector_2048_read(This, MediaId, Lba / 4, ReadSize, CurBuf);
|
||||
CurBuf += ReadSize;
|
||||
|
||||
Lba += ReadSize / 512;
|
||||
BufferSize -= ReadSize;
|
||||
}
|
||||
|
||||
if (BufferSize > 0)
|
||||
{
|
||||
Status |= g_sector_2048_read(This, MediaId, Lba / 4, 2048, g_sector_buf);
|
||||
CopyMem(CurBuf, g_sector_buf, BufferSize);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_block_io_write_512
|
||||
(
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSize,
|
||||
IN VOID *Buffer
|
||||
)
|
||||
{
|
||||
EFI_LBA Mod;
|
||||
UINTN ReadSize;
|
||||
UINT8 *CurBuf = NULL;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
|
||||
debug("ventoy_block_io_write_512 %lu %lu\n", Lba, BufferSize / 512);
|
||||
|
||||
CurBuf = (UINT8 *)Buffer;
|
||||
|
||||
Mod = Lba % 4;
|
||||
if (Mod > 0)
|
||||
{
|
||||
Status |= g_sector_2048_read(This, MediaId, Lba / 4, 2048, g_sector_buf);
|
||||
|
||||
if (BufferSize <= (4 - Mod) * 512)
|
||||
{
|
||||
CopyMem(g_sector_buf + Mod * 512, CurBuf, BufferSize);
|
||||
return g_sector_2048_write(This, MediaId, Lba / 4, 2048, g_sector_buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
ReadSize = (4 - Mod) * 512;
|
||||
CopyMem(g_sector_buf + Mod * 512, CurBuf, ReadSize);
|
||||
g_sector_2048_write(This, MediaId, Lba / 4, 2048, g_sector_buf);
|
||||
|
||||
CurBuf += ReadSize;
|
||||
Lba += (4 - Mod);
|
||||
BufferSize -= ReadSize;
|
||||
}
|
||||
}
|
||||
|
||||
if (BufferSize >= 2048)
|
||||
{
|
||||
ReadSize = BufferSize / 2048 * 2048;
|
||||
|
||||
Status |= g_sector_2048_write(This, MediaId, Lba / 4, ReadSize, CurBuf);
|
||||
CurBuf += ReadSize;
|
||||
|
||||
Lba += ReadSize / 512;
|
||||
BufferSize -= ReadSize;
|
||||
}
|
||||
|
||||
if (BufferSize > 0)
|
||||
{
|
||||
Status |= g_sector_2048_read(This, MediaId, Lba / 4, 2048, g_sector_buf);
|
||||
|
||||
CopyMem(g_sector_buf, CurBuf, BufferSize);
|
||||
g_sector_2048_write(This, MediaId, Lba / 4, 2048, g_sector_buf);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_install_blockio(IN EFI_HANDLE ImageHandle, IN UINT64 ImgSize)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_BLOCK_IO_PROTOCOL *pBlockIo = &(gBlockData.BlockIo);
|
||||
|
||||
ventoy_fill_device_path();
|
||||
|
||||
debug("install block io protocol %p", ImageHandle);
|
||||
ventoy_debug_pause();
|
||||
|
||||
if (gSector512Mode)
|
||||
{
|
||||
gBlockData.Media.BlockSize = 512;
|
||||
gBlockData.Media.LastBlock = ImgSize / 512 - 1;
|
||||
gBlockData.Media.ReadOnly = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
gBlockData.Media.BlockSize = 2048;
|
||||
gBlockData.Media.LastBlock = ImgSize / 2048 - 1;
|
||||
gBlockData.Media.ReadOnly = TRUE;
|
||||
}
|
||||
|
||||
gBlockData.Media.BlockSize = 2048;
|
||||
gBlockData.Media.LastBlock = ImgSize / 2048 - 1;
|
||||
gBlockData.Media.ReadOnly = TRUE;
|
||||
gBlockData.Media.MediaPresent = 1;
|
||||
gBlockData.Media.LogicalBlocksPerPhysicalBlock = 1;
|
||||
|
||||
pBlockIo->Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3;
|
||||
pBlockIo->Media = &(gBlockData.Media);
|
||||
pBlockIo->Reset = ventoy_block_io_reset;
|
||||
pBlockIo->ReadBlocks = gMemdiskMode ? ventoy_block_io_ramdisk_read : ventoy_block_io_read;
|
||||
pBlockIo->WriteBlocks = ventoy_block_io_write;
|
||||
|
||||
if (gSector512Mode)
|
||||
{
|
||||
g_sector_2048_read = gMemdiskMode ? ventoy_block_io_ramdisk_read : ventoy_block_io_read;
|
||||
g_sector_2048_write = gMemdiskMode ? ventoy_block_io_ramdisk_write : ventoy_block_io_write;
|
||||
pBlockIo->ReadBlocks = ventoy_block_io_read_512;
|
||||
pBlockIo->WriteBlocks = ventoy_block_io_write_512;
|
||||
}
|
||||
else
|
||||
{
|
||||
pBlockIo->ReadBlocks = gMemdiskMode ? ventoy_block_io_ramdisk_read : ventoy_block_io_read;
|
||||
pBlockIo->WriteBlocks = ventoy_block_io_write;
|
||||
}
|
||||
|
||||
pBlockIo->FlushBlocks = ventoy_block_io_flush;
|
||||
|
||||
Status = gBS->InstallMultipleProtocolInterfaces(&gBlockData.Handle,
|
||||
@ -558,11 +1178,10 @@ EFI_STATUS EFIAPI ventoy_install_blockio(IN EFI_HANDLE ImageHandle, IN UINT64 Im
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
Status = ventoy_connect_driver(gBlockData.Handle, L"Disk I/O Driver");
|
||||
debug("Connect disk IO driver %r", Status);
|
||||
ventoy_debug_pause();
|
||||
|
||||
|
||||
Status = ventoy_connect_driver(gBlockData.Handle, L"Partition Driver");
|
||||
debug("Connect partition driver %r", Status);
|
||||
if (EFI_ERROR(Status))
|
||||
@ -656,8 +1275,16 @@ STATIC EFI_STATUS EFIAPI
|
||||
ventoy_wrapper_file_set_pos(EFI_FILE_HANDLE This, UINT64 Position)
|
||||
{
|
||||
(VOID)This;
|
||||
|
||||
if (Position <= g_efi_file_replace.FileSizeBytes)
|
||||
{
|
||||
g_efi_file_replace.CurPos = Position;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_efi_file_replace.CurPos = g_efi_file_replace.FileSizeBytes;
|
||||
}
|
||||
|
||||
g_efi_file_replace.CurPos = Position;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
@ -772,6 +1399,18 @@ STATIC EFI_STATUS EFIAPI ventoy_wrapper_file_open
|
||||
CHAR8 TmpName[256];
|
||||
ventoy_virt_chunk *virt = NULL;
|
||||
|
||||
debug("## ventoy_wrapper_file_open <%s> ", Name);
|
||||
|
||||
if ((Mode & EFI_FILE_MODE_WRITE) > 0 && StrCmp(Name, L"\\loader\\random-seed") == 0)
|
||||
{
|
||||
if (gDebugPrint)
|
||||
{
|
||||
debug("## ventoy_wrapper_file_open return NOT_FOUND for random-seed %lx", Mode);
|
||||
sleep(3);
|
||||
}
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
Status = g_original_fopen(This, New, Name, Mode, Attributes);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
@ -807,6 +1446,11 @@ STATIC EFI_STATUS EFIAPI ventoy_wrapper_file_open
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
if (StrCmp(Name, L"\\EFI\\BOOT") == 0)
|
||||
{
|
||||
(*New)->Open = ventoy_wrapper_file_open;
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
@ -916,3 +1560,55 @@ EFI_STATUS ventoy_hook_keyboard_stop(VOID)
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Fixup the 1st cdrom influnce for Windows boot */
|
||||
#endif
|
||||
|
||||
STATIC EFI_STATUS EFIAPI ventoy_wrapper_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 = NULL;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
|
||||
Status = g_org_locate_handle(SearchType, Protocol, SearchKey, BufferSize, Buffer);
|
||||
|
||||
if (EFI_SUCCESS == Status && Protocol && CompareGuid(&gEfiBlockIoProtocolGuid, Protocol))
|
||||
{
|
||||
for (i = 0; i < (*BufferSize) / sizeof(EFI_HANDLE); i++)
|
||||
{
|
||||
if (Buffer[i] == gBlockData.Handle)
|
||||
{
|
||||
Handle = Buffer[0];
|
||||
Buffer[0] = Buffer[i];
|
||||
Buffer[i] = Handle;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS ventoy_hook_1st_cdrom_start(VOID)
|
||||
{
|
||||
g_org_locate_handle = gBS->LocateHandle;
|
||||
gBS->LocateHandle = ventoy_wrapper_locate_handle;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS ventoy_hook_1st_cdrom_stop(VOID)
|
||||
{
|
||||
gBS->LocateHandle = g_org_locate_handle;
|
||||
g_org_locate_handle = NULL;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,179 @@
|
||||
/******************************************************************************
|
||||
* Memhole.c
|
||||
*
|
||||
* Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Uefi.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/PrintLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DevicePathLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||
#include <Library/UefiApplicationEntryPoint.h>
|
||||
#include <Protocol/LoadedImage.h>
|
||||
#include <Guid/FileInfo.h>
|
||||
#include <Guid/FileSystemInfo.h>
|
||||
#include <Protocol/BlockIo.h>
|
||||
#include <Protocol/RamDisk.h>
|
||||
#include <Protocol/SimpleFileSystem.h>
|
||||
#include <VtoyUtil.h>
|
||||
|
||||
STATIC BOOLEAN IsMemContiguous
|
||||
(
|
||||
IN CONST EFI_MEMORY_DESCRIPTOR *Prev,
|
||||
IN CONST EFI_MEMORY_DESCRIPTOR *Curr,
|
||||
IN CONST EFI_MEMORY_DESCRIPTOR *Next
|
||||
)
|
||||
{
|
||||
UINTN Addr1 = 0;
|
||||
UINTN Addr2 = 0;
|
||||
|
||||
if (Prev == NULL || Curr == NULL || Next == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (Prev->Type == EfiBootServicesData &&
|
||||
Curr->Type == EfiConventionalMemory &&
|
||||
Next->Type == EfiBootServicesData)
|
||||
{
|
||||
Addr1 = Prev->PhysicalStart + MultU64x64(SIZE_4KB, Prev->NumberOfPages);
|
||||
Addr2 = Curr->PhysicalStart + MultU64x64(SIZE_4KB, Curr->NumberOfPages);
|
||||
|
||||
if (Addr1 == Curr->PhysicalStart && Addr2 == Next->PhysicalStart)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
STATIC EFI_MEMORY_DESCRIPTOR* GetMemDesc
|
||||
(
|
||||
OUT UINTN *pSize,
|
||||
OUT UINTN *pItemSize,
|
||||
OUT UINTN *pDescCount
|
||||
)
|
||||
{
|
||||
UINTN Size = 0;
|
||||
UINTN MapKey = 0;
|
||||
UINTN ItemSize = 0;
|
||||
UINTN DescCount = 0;
|
||||
UINT32 Version = 0;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_MEMORY_DESCRIPTOR *pDesc = NULL;
|
||||
EFI_MEMORY_DESCRIPTOR *Curr = NULL;
|
||||
|
||||
Status = gBS->GetMemoryMap(&Size, pDesc, &MapKey, &ItemSize, &Version);
|
||||
if (EFI_BUFFER_TOO_SMALL != Status)
|
||||
{
|
||||
debug("GetMemoryMap: %r", Status);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Size += SIZE_1KB;
|
||||
pDesc = AllocatePool(Size);
|
||||
if (!pDesc)
|
||||
{
|
||||
debug("AllocatePool: %lu failed", Size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ZeroMem(pDesc, Size);
|
||||
|
||||
Status = gBS->GetMemoryMap(&Size, pDesc, &MapKey, &ItemSize, &Version);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
debug("GetMemoryMap: %r", Status);
|
||||
FreePool(pDesc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Curr = pDesc;
|
||||
while (Curr && Curr < (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)pDesc + Size))
|
||||
{
|
||||
DescCount++;
|
||||
Curr = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)Curr + ItemSize);
|
||||
}
|
||||
|
||||
*pSize = Size;
|
||||
*pItemSize = ItemSize;
|
||||
*pDescCount = DescCount;
|
||||
|
||||
debug("GetMemoryMap: ItemSize:%lu Count:%lu", ItemSize, DescCount);
|
||||
|
||||
return pDesc;
|
||||
}
|
||||
|
||||
EFI_STATUS FixWindowsMemhole(IN EFI_HANDLE ImageHandle, IN CONST CHAR16 *CmdLine)
|
||||
{
|
||||
UINTN Size = 0;
|
||||
UINTN ItemSize = 0;
|
||||
UINTN DescCount = 0;
|
||||
UINTN TotalMem = 0;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_PHYSICAL_ADDRESS AllocAddr = 0;
|
||||
EFI_MEMORY_DESCRIPTOR *pDescs = NULL;
|
||||
EFI_MEMORY_DESCRIPTOR *Prev = NULL;
|
||||
EFI_MEMORY_DESCRIPTOR *Next = NULL;
|
||||
EFI_MEMORY_DESCRIPTOR *Curr = NULL;
|
||||
|
||||
(VOID)ImageHandle;
|
||||
(VOID)CmdLine;
|
||||
|
||||
pDescs = GetMemDesc(&Size, &ItemSize, &DescCount);
|
||||
if (!pDescs)
|
||||
{
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (DescCount < 500)
|
||||
{
|
||||
FreePool(pDescs);
|
||||
Printf("There is no need to fixup (%lu)\n", DescCount);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
Curr = pDescs;
|
||||
while ((UINT8 *)Curr < (UINT8 *)pDescs + Size)
|
||||
{
|
||||
Next = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)Curr + ItemSize);
|
||||
|
||||
if (IsMemContiguous(Prev, Curr, Next))
|
||||
{
|
||||
AllocAddr = Curr->PhysicalStart;
|
||||
Status = gBS->AllocatePages(AllocateAddress, EfiBootServicesData, Curr->NumberOfPages, &AllocAddr);
|
||||
if (EFI_SUCCESS == Status)
|
||||
{
|
||||
TotalMem += MultU64x64(SIZE_4KB, Curr->NumberOfPages);
|
||||
}
|
||||
}
|
||||
|
||||
Prev = Curr;
|
||||
Curr = Next;
|
||||
}
|
||||
|
||||
Printf("Fixup Windows mmap issue OK (%lu)\n", TotalMem);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
@ -0,0 +1,140 @@
|
||||
/******************************************************************************
|
||||
* VtoyDrv.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 UINTN g_EfiDriverNameCnt = 0;
|
||||
STATIC CHAR16 *g_EfiDriverNameList[1024] = { NULL };
|
||||
|
||||
STATIC EFI_STATUS AddEfiDriverName(IN CHAR16 *DriverName)
|
||||
{
|
||||
UINTN i = 0;
|
||||
|
||||
if (g_EfiDriverNameCnt >= 1024)
|
||||
{
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
for (i = 0; i < g_EfiDriverNameCnt; i++)
|
||||
{
|
||||
if (g_EfiDriverNameList[i] && StrCmp(g_EfiDriverNameList[i], DriverName) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= g_EfiDriverNameCnt)
|
||||
{
|
||||
g_EfiDriverNameList[g_EfiDriverNameCnt] = DriverName;
|
||||
g_EfiDriverNameCnt++;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS ShowEfiDrivers(IN EFI_HANDLE ImageHandle, IN CONST CHAR16 *CmdLine)
|
||||
{
|
||||
UINTN i = 0;
|
||||
UINTN Count = 0;
|
||||
CHAR16 *DriverName = NULL;
|
||||
EFI_HANDLE *Handles = NULL;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_COMPONENT_NAME_PROTOCOL *NameProtocol = NULL;
|
||||
EFI_COMPONENT_NAME2_PROTOCOL *Name2Protocol = NULL;
|
||||
|
||||
(VOID)ImageHandle;
|
||||
(VOID)CmdLine;
|
||||
|
||||
Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiComponentName2ProtocolGuid,
|
||||
NULL, &Count, &Handles);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
for (i = 0; i < Count; i++)
|
||||
{
|
||||
Status = gBS->HandleProtocol(Handles[i], &gEfiComponentName2ProtocolGuid, (VOID **)&Name2Protocol);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
DriverName = NULL;
|
||||
Status = VtoyGetComponentName(2, Name2Protocol, &DriverName);
|
||||
if ((!EFI_ERROR(Status)) && (DriverName))
|
||||
{
|
||||
AddEfiDriverName(DriverName);
|
||||
}
|
||||
}
|
||||
|
||||
Count = 0;
|
||||
FreePool(Handles);
|
||||
Handles = NULL;
|
||||
|
||||
Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiComponentNameProtocolGuid,
|
||||
NULL, &Count, &Handles);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
for (i = 0; i < Count; i++)
|
||||
{
|
||||
Status = gBS->HandleProtocol(Handles[i], &gEfiComponentNameProtocolGuid, (VOID **)&NameProtocol);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
DriverName = NULL;
|
||||
Status = VtoyGetComponentName(1, Name2Protocol, &DriverName);
|
||||
if ((!EFI_ERROR(Status)) && (DriverName))
|
||||
{
|
||||
AddEfiDriverName(DriverName);
|
||||
}
|
||||
}
|
||||
|
||||
FreePool(Handles);
|
||||
|
||||
for (i = 0; i < g_EfiDriverNameCnt; i++)
|
||||
{
|
||||
Printf("%2d %s\n", i, g_EfiDriverNameList[i]);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
@ -0,0 +1,178 @@
|
||||
/******************************************************************************
|
||||
* 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 },
|
||||
{ L"show_efi_drivers", ShowEfiDrivers },
|
||||
};
|
||||
|
||||
EFI_STATUS VtoyGetComponentName(IN UINTN Ver, IN VOID *Protocol, OUT CHAR16 **DriverName)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
CHAR16 *DrvName = NULL;
|
||||
EFI_COMPONENT_NAME_PROTOCOL *NameProtocol = NULL;
|
||||
EFI_COMPONENT_NAME2_PROTOCOL *Name2Protocol = NULL;
|
||||
|
||||
if (1 == Ver)
|
||||
{
|
||||
NameProtocol = (EFI_COMPONENT_NAME_PROTOCOL *)Protocol;
|
||||
Status = NameProtocol->GetDriverName(Protocol, "en", &DrvName);
|
||||
if (EFI_ERROR(Status) || NULL == DrvName)
|
||||
{
|
||||
Status = NameProtocol->GetDriverName(Protocol, "eng", &DrvName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Name2Protocol = (EFI_COMPONENT_NAME2_PROTOCOL *)Protocol;
|
||||
Status = Name2Protocol->GetDriverName(Protocol, "en", &DrvName);
|
||||
if (EFI_ERROR(Status) || NULL == DrvName)
|
||||
{
|
||||
Status = Name2Protocol->GetDriverName(Protocol, "eng", &DrvName);
|
||||
}
|
||||
}
|
||||
|
||||
*DriverName = DrvName;
|
||||
return Status;
|
||||
}
|
||||
|
||||
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"vtoyefitest"))
|
||||
{
|
||||
gST->ConOut->OutputString(gST->ConOut, L"\r\n##########################");
|
||||
gST->ConOut->OutputString(gST->ConOut, L"\r\n######### VTOY #########");
|
||||
gST->ConOut->OutputString(gST->ConOut, L"\r\n##########################");
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
if (StrStr(pCmdLine, L"debug"))
|
||||
{
|
||||
gVtoyDebugPrint = TRUE;
|
||||
}
|
||||
|
||||
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; gCurFeature && 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;
|
||||
}
|
||||
}
|
||||
|
||||
if (gCmdLine)
|
||||
{
|
||||
FreePool(gCmdLine);
|
||||
gCmdLine = NULL;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
@ -0,0 +1,65 @@
|
||||
/******************************************************************************
|
||||
* 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 VtoyGetComponentName(IN UINTN Ver, IN VOID *Protocol, OUT CHAR16 **DriverName);
|
||||
EFI_STATUS FixWindowsMemhole(IN EFI_HANDLE ImageHandle, IN CONST CHAR16 *CmdLine);
|
||||
EFI_STATUS ShowEfiDrivers(IN EFI_HANDLE ImageHandle, IN CONST CHAR16 *CmdLine);
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,81 @@
|
||||
#************************************************************************************
|
||||
# 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
|
||||
VtoyDrv.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,8 @@
|
||||
|
||||
[Components]
|
||||
MdeModulePkg/Application/Ventoy/Ventoy.inf
|
||||
MdeModulePkg/Application/VtoyUtil/VtoyUtil.inf
|
||||
MdeModulePkg/Application/VDiskChain/VDiskChain.inf
|
||||
MdeModulePkg/Application/HelloWorld/HelloWorld.inf
|
||||
MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.inf
|
||||
MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf
|
||||
|
@ -743,8 +743,8 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
|
||||
if (!ctx.filename && dirent.namelen == 1 && name[0] == 1)
|
||||
ctx.filename = (char *) "..";
|
||||
|
||||
if (g_fs_name_nocase)
|
||||
ctx.type |= GRUB_FSHELP_CASE_INSENSITIVE;
|
||||
if (g_fs_name_nocase)
|
||||
ctx.type |= GRUB_FSHELP_CASE_INSENSITIVE;
|
||||
|
||||
/* The filename was not stored in a rock ridge entry. Read it
|
||||
from the iso9660 filesystem. */
|
||||
|
@ -70,10 +70,10 @@ SetLogging(VOID)
|
||||
CHAR16 LogVar[4];
|
||||
UINTN i, LogVarSize = sizeof(LogVar);
|
||||
|
||||
i = LogVarSize;
|
||||
i = LogVarSize;
|
||||
Status = RT->GetVariable(L"FS_NAME_NOCASE", &ShellVariable, NULL, &i, LogVar);
|
||||
if (Status == EFI_SUCCESS)
|
||||
g_fs_name_nocase = 1;
|
||||
if (Status == EFI_SUCCESS)
|
||||
g_fs_name_nocase = 1;
|
||||
|
||||
Status = RT->GetVariable(L"FS_LOGGING", &ShellVariable, NULL, &LogVarSize, LogVar);
|
||||
if (Status == EFI_SUCCESS)
|
||||
|
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/
|
||||
|
32
ExFAT/buidexfat_aarch64.sh
Normal file
32
ExFAT/buidexfat_aarch64.sh
Normal file
@ -0,0 +1,32 @@
|
||||
#!/bin/bash
|
||||
|
||||
CUR="$PWD"
|
||||
|
||||
if ! [ -e LIBFUSE ]; then
|
||||
./buidlibfuse.sh
|
||||
fi
|
||||
|
||||
rm -f EXFAT/shared/*
|
||||
|
||||
|
||||
rm -rf exfat-1.3.0
|
||||
unzip exfat-1.3.0.zip
|
||||
sed "/printf.*VERSION/a\ if (access(\"/etc/initrd-release\", F_OK) >= 0) argv[0][0] = '@';" -i exfat-1.3.0/fuse/main.c
|
||||
|
||||
cd exfat-1.3.0
|
||||
autoreconf --install
|
||||
./configure --prefix="$CUR" CFLAGS='-O2 -D_FILE_OFFSET_BITS=64' FUSE_CFLAGS="-I$CUR/LIBFUSE/include/" FUSE_LIBS="$CUR/LIBFUSE/lib/libfuse.a -lpthread -ldl"
|
||||
make
|
||||
|
||||
strip --strip-all fuse/mount.exfat-fuse
|
||||
strip --strip-all mkfs/mkexfatfs
|
||||
|
||||
cp fuse/mount.exfat-fuse ../EXFAT/shared/mount.exfat-fuse
|
||||
cp mkfs/mkexfatfs ../EXFAT/shared/mkexfatfs
|
||||
|
||||
cd ..
|
||||
rm -rf exfat-1.3.0
|
||||
|
||||
|
||||
|
||||
|
29
ExFAT/buidlibfuse_aarch64.sh
Normal file
29
ExFAT/buidlibfuse_aarch64.sh
Normal file
@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
|
||||
CUR="$PWD"
|
||||
|
||||
rm -rf libfuse
|
||||
rm -rf LIBFUSE
|
||||
|
||||
if [ -e mirrors-libfuse-fuse-2.9.9.zip ]; then
|
||||
unzip mirrors-libfuse-fuse-2.9.9.zip
|
||||
cd libfuse
|
||||
else
|
||||
unzip libfuse-fuse-2.9.9.zip
|
||||
cd libfuse-fuse-2.9.9
|
||||
fi
|
||||
|
||||
./makeconf.sh
|
||||
|
||||
./configure --prefix="$CUR/LIBFUSE"
|
||||
|
||||
sed '/#define *__u64/d' -i include/fuse_kernel.h
|
||||
sed '/#define *__s64/d' -i include/fuse_kernel.h
|
||||
|
||||
sed 's/__u64/uint64_t/g' -i include/fuse_kernel.h
|
||||
sed 's/__s64/int64_t/g' -i include/fuse_kernel.h
|
||||
|
||||
make -j 16
|
||||
make install
|
||||
cd ..
|
||||
rm -rf libfuse
|
@ -11,10 +11,16 @@ else
|
||||
opt=-lrt
|
||||
fi
|
||||
|
||||
#
|
||||
# use musl-c to build for x86_64
|
||||
#
|
||||
|
||||
export C_INCLUDE_PATH=$LIBFUSE_DIR/include
|
||||
|
||||
rm -f $name
|
||||
gcc -static -O2 -D_FILE_OFFSET_BITS=64 vtoy_fuse_iso.c -o $name $LIBFUSE_DIR/lib/libfuse.a -lpthread -ldl $opt
|
||||
gcc -specs "/usr/local/musl/lib/musl-gcc.specs" -static -O2 -D_FILE_OFFSET_BITS=64 vtoy_fuse_iso.c $LIBFUSE_DIR/lib/libfuse.a -o $name
|
||||
|
||||
strip --strip-all $name
|
||||
|
||||
if [ -e $name ]; then
|
||||
echo -e "\n############### SUCCESS $name ##################\n"
|
||||
|
21
FUSEISO/build_aarch64.sh
Normal file
21
FUSEISO/build_aarch64.sh
Normal file
@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
|
||||
CUR="$PWD"
|
||||
|
||||
LIBFUSE_DIR=$CUR/LIBFUSE
|
||||
|
||||
name=vtoy_fuse_iso_aa64
|
||||
|
||||
export C_INCLUDE_PATH=$LIBFUSE_DIR/include
|
||||
|
||||
rm -f $name
|
||||
aarch64-buildroot-linux-uclibc-gcc -static -O2 -D_FILE_OFFSET_BITS=64 vtoy_fuse_iso.c -o $name $LIBFUSE_DIR/lib/libfuse.a
|
||||
|
||||
if [ -e $name ]; then
|
||||
echo -e "\n############### SUCCESS $name ##################\n"
|
||||
else
|
||||
echo -e "\n############### FAILED $name ##################\n"
|
||||
fi
|
||||
|
||||
aarch64-buildroot-linux-uclibc-strip --strip-all $name
|
||||
|
@ -7,6 +7,8 @@
|
||||
#
|
||||
#
|
||||
|
||||
# use mini-native-x86_64 UCLIBC to build for x86_64
|
||||
|
||||
|
||||
CUR="$PWD"
|
||||
LIBFUSE_DIR=$CUR/LIBFUSE
|
||||
@ -31,7 +33,7 @@ fi
|
||||
|
||||
./makeconf.sh
|
||||
|
||||
./configure --prefix="$LIBFUSE_DIR"
|
||||
./configure --prefix="$LIBFUSE_DIR" CFLAGS='-specs /usr/local/musl/lib/musl-gcc.specs'
|
||||
make -j 16
|
||||
make install
|
||||
cd ..
|
||||
|
46
FUSEISO/build_libfuse_aarch64.sh
Normal file
46
FUSEISO/build_libfuse_aarch64.sh
Normal file
@ -0,0 +1,46 @@
|
||||
#!/bin/bash
|
||||
|
||||
#
|
||||
#
|
||||
# Package Dependency:
|
||||
# gcc automake autoconf gettext gettext-devel libtool unzip
|
||||
#
|
||||
#
|
||||
|
||||
|
||||
CUR="$PWD"
|
||||
LIBFUSE_DIR=$CUR/LIBFUSE
|
||||
|
||||
rm -rf libfuse
|
||||
rm -rf $LIBFUSE_DIR
|
||||
|
||||
# please download https://codeload.github.com/libfuse/libfuse/zip/fuse-2.9.9
|
||||
if [ -e ../ExFAT/mirrors-libfuse-fuse-2.9.9.zip ]; then
|
||||
rm -rf libfuse
|
||||
unzip ../ExFAT/mirrors-libfuse-fuse-2.9.9.zip
|
||||
cd libfuse
|
||||
elif [ -e ../ExFAT/libfuse-fuse-2.9.9.zip ]; then
|
||||
rm -rf libfuse-fuse-2.9.9
|
||||
unzip ../ExFAT/libfuse-fuse-2.9.9.zip
|
||||
cd libfuse-fuse-2.9.9
|
||||
else
|
||||
echo "Please download mirrors-libfuse-fuse-2.9.9.zip first"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
./makeconf.sh
|
||||
|
||||
sed '/#define *__u64/d' -i include/fuse_kernel.h
|
||||
sed '/#define *__s64/d' -i include/fuse_kernel.h
|
||||
|
||||
sed 's/__u64/uint64_t/g' -i include/fuse_kernel.h
|
||||
sed 's/__s64/int64_t/g' -i include/fuse_kernel.h
|
||||
|
||||
./configure --prefix="$LIBFUSE_DIR" --host=aarch64 CC=aarch64-buildroot-linux-uclibc-gcc
|
||||
|
||||
|
||||
make -j 16
|
||||
make install
|
||||
cd ..
|
||||
rm -rf libfuse
|
@ -114,11 +114,12 @@ static int ventoy_iso_open(const char *path, struct fuse_file_info *file)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ventoy_read_iso_sector(uint32_t sector, uint32_t num, void *buf)
|
||||
static int ventoy_read_iso_sector(uint32_t sector, uint32_t num, char *buf)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint32_t leftSec = 0;
|
||||
uint32_t readSec = 0;
|
||||
off_t offset = 0;
|
||||
dmtable_entry *entry = NULL;
|
||||
|
||||
for (i = 0; i < g_disk_entry_num && num > 0; i++)
|
||||
@ -127,14 +128,15 @@ static int ventoy_read_iso_sector(uint32_t sector, uint32_t num, void *buf)
|
||||
|
||||
if (sector >= entry->isoSector && sector < entry->isoSector + entry->sectorNum)
|
||||
{
|
||||
lseek(g_disk_fd, (entry->diskSector + (sector - entry->isoSector)) * 512, SEEK_SET);
|
||||
offset = (entry->diskSector + (sector - entry->isoSector)) * 512;
|
||||
|
||||
leftSec = entry->sectorNum - (sector - entry->isoSector);
|
||||
readSec = (leftSec > num) ? num : leftSec;
|
||||
|
||||
read(g_disk_fd, buf, readSec * 512);
|
||||
pread(g_disk_fd, buf, readSec * 512, offset);
|
||||
|
||||
sector += readSec;
|
||||
buf += readSec * 512;
|
||||
num -= readSec;
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
Binary file not shown.
BIN
FUSEISO/vtoy_fuse_iso_aa64
Normal file
BIN
FUSEISO/vtoy_fuse_iso_aa64
Normal file
Binary file not shown.
2123
GRUB2/MOD_SRC/grub-2.04/configure.ac
Normal file
2123
GRUB2/MOD_SRC/grub-2.04/configure.ac
Normal file
File diff suppressed because it is too large
Load Diff
909
GRUB2/MOD_SRC/grub-2.04/gentpl.py
Normal file
909
GRUB2/MOD_SRC/grub-2.04/gentpl.py
Normal file
@ -0,0 +1,909 @@
|
||||
#! /usr/bin/python
|
||||
# GRUB -- GRand Unified Bootloader
|
||||
# Copyright (C) 2010,2011,2012,2013 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/>.
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
from optparse import OptionParser
|
||||
import re
|
||||
|
||||
#
|
||||
# This is the python script used to generate Makefile.*.am
|
||||
#
|
||||
|
||||
GRUB_PLATFORMS = [ "emu", "i386_pc", "i386_efi", "i386_qemu", "i386_coreboot",
|
||||
"i386_multiboot", "i386_ieee1275", "x86_64_efi",
|
||||
"i386_xen", "x86_64_xen", "i386_xen_pvh",
|
||||
"mips_loongson", "mips64_efi", "sparc64_ieee1275",
|
||||
"powerpc_ieee1275", "mips_arc", "ia64_efi",
|
||||
"mips_qemu_mips", "arm_uboot", "arm_efi", "arm64_efi",
|
||||
"arm_coreboot", "riscv32_efi", "riscv64_efi" ]
|
||||
|
||||
GROUPS = {}
|
||||
|
||||
GROUPS["common"] = GRUB_PLATFORMS[:]
|
||||
|
||||
# Groups based on CPU
|
||||
GROUPS["i386"] = [ "i386_pc", "i386_efi", "i386_qemu", "i386_coreboot", "i386_multiboot", "i386_ieee1275" ]
|
||||
GROUPS["x86_64"] = [ "x86_64_efi" ]
|
||||
GROUPS["x86"] = GROUPS["i386"] + GROUPS["x86_64"]
|
||||
GROUPS["mips"] = [ "mips_loongson", "mips_qemu_mips", "mips_arc" ]
|
||||
GROUPS["mips64"] = [ "mips64_efi" ]
|
||||
GROUPS["sparc64"] = [ "sparc64_ieee1275" ]
|
||||
GROUPS["powerpc"] = [ "powerpc_ieee1275" ]
|
||||
GROUPS["arm"] = [ "arm_uboot", "arm_efi", "arm_coreboot" ]
|
||||
GROUPS["arm64"] = [ "arm64_efi" ]
|
||||
GROUPS["riscv32"] = [ "riscv32_efi" ]
|
||||
GROUPS["riscv64"] = [ "riscv64_efi" ]
|
||||
|
||||
# Groups based on firmware
|
||||
GROUPS["efi"] = [ "i386_efi", "x86_64_efi", "ia64_efi", "arm_efi", "arm64_efi", "mips64_efi",
|
||||
"riscv32_efi", "riscv64_efi" ]
|
||||
GROUPS["ieee1275"] = [ "i386_ieee1275", "sparc64_ieee1275", "powerpc_ieee1275" ]
|
||||
GROUPS["uboot"] = [ "arm_uboot" ]
|
||||
GROUPS["xen"] = [ "i386_xen", "x86_64_xen" ]
|
||||
GROUPS["coreboot"] = [ "i386_coreboot", "arm_coreboot" ]
|
||||
|
||||
# emu is a special case so many core functionality isn't needed on this platform
|
||||
GROUPS["noemu"] = GRUB_PLATFORMS[:]; GROUPS["noemu"].remove("emu")
|
||||
|
||||
# Groups based on hardware features
|
||||
GROUPS["cmos"] = GROUPS["x86"][:] + ["mips_loongson", "mips_qemu_mips",
|
||||
"sparc64_ieee1275", "powerpc_ieee1275"]
|
||||
GROUPS["cmos"].remove("i386_efi"); GROUPS["cmos"].remove("x86_64_efi");
|
||||
GROUPS["pci"] = GROUPS["x86"] + ["mips_loongson"]
|
||||
GROUPS["usb"] = GROUPS["pci"] + ["arm_coreboot"]
|
||||
|
||||
# If gfxterm is main output console integrate it into kernel
|
||||
GROUPS["videoinkernel"] = ["mips_loongson", "i386_coreboot", "arm_coreboot" ]
|
||||
GROUPS["videomodules"] = GRUB_PLATFORMS[:];
|
||||
for i in GROUPS["videoinkernel"]: GROUPS["videomodules"].remove(i)
|
||||
|
||||
# Similar for terminfo
|
||||
GROUPS["terminfoinkernel"] = [ "emu", "mips_loongson", "mips_arc", "mips_qemu_mips", "i386_xen_pvh" ] + GROUPS["xen"] + GROUPS["ieee1275"] + GROUPS["uboot"];
|
||||
GROUPS["terminfomodule"] = GRUB_PLATFORMS[:];
|
||||
for i in GROUPS["terminfoinkernel"]: GROUPS["terminfomodule"].remove(i)
|
||||
|
||||
# Flattened Device Trees (FDT)
|
||||
GROUPS["fdt"] = [ "arm64_efi", "arm_uboot", "arm_efi", "riscv32_efi", "riscv64_efi" ]
|
||||
|
||||
# Needs software helpers for division
|
||||
# Must match GRUB_DIVISION_IN_SOFTWARE in misc.h
|
||||
GROUPS["softdiv"] = GROUPS["arm"] + ["ia64_efi"] + GROUPS["riscv32"]
|
||||
GROUPS["no_softdiv"] = GRUB_PLATFORMS[:]
|
||||
for i in GROUPS["softdiv"]: GROUPS["no_softdiv"].remove(i)
|
||||
|
||||
# Miscellaneous groups scheduled to disappear in future
|
||||
GROUPS["i386_coreboot_multiboot_qemu"] = ["i386_coreboot", "i386_multiboot", "i386_qemu"]
|
||||
GROUPS["nopc"] = GRUB_PLATFORMS[:]; GROUPS["nopc"].remove("i386_pc")
|
||||
|
||||
#
|
||||
# Create platform => groups reverse map, where groups covering that
|
||||
# platform are ordered by their sizes
|
||||
#
|
||||
RMAP = {}
|
||||
for platform in GRUB_PLATFORMS:
|
||||
# initialize with platform itself as a group
|
||||
RMAP[platform] = [ platform ]
|
||||
|
||||
for k in GROUPS.keys():
|
||||
v = GROUPS[k]
|
||||
# skip groups that don't cover this platform
|
||||
if platform not in v: continue
|
||||
|
||||
bigger = []
|
||||
smaller = []
|
||||
# partition currently known groups based on their size
|
||||
for group in RMAP[platform]:
|
||||
if group in GRUB_PLATFORMS: smaller.append(group)
|
||||
elif len(GROUPS[group]) < len(v): smaller.append(group)
|
||||
else: bigger.append(group)
|
||||
# insert in the middle
|
||||
RMAP[platform] = smaller + [ k ] + bigger
|
||||
|
||||
#
|
||||
# Input
|
||||
#
|
||||
|
||||
# We support a subset of the AutoGen definitions file syntax. Specifically,
|
||||
# compound names are disallowed; some preprocessing directives are
|
||||
# disallowed (though #if/#endif are allowed; note that, like AutoGen, #if
|
||||
# skips everything to the next #endif regardless of the value of the
|
||||
# conditional); and shell-generated strings, Scheme-generated strings, and
|
||||
# here strings are disallowed.
|
||||
|
||||
class AutogenToken:
|
||||
(autogen, definitions, eof, var_name, other_name, string, number,
|
||||
semicolon, equals, comma, lbrace, rbrace, lbracket, rbracket) = range(14)
|
||||
|
||||
class AutogenState:
|
||||
(init, need_def, need_tpl, need_semi, need_name, have_name, need_value,
|
||||
need_idx, need_rbracket, indx_name, have_value, done) = range(12)
|
||||
|
||||
class AutogenParseError(Exception):
|
||||
def __init__(self, message, path, line):
|
||||
super(AutogenParseError, self).__init__(message)
|
||||
self.path = path
|
||||
self.line = line
|
||||
|
||||
def __str__(self):
|
||||
return (
|
||||
super(AutogenParseError, self).__str__() +
|
||||
" at file %s line %d" % (self.path, self.line))
|
||||
|
||||
class AutogenDefinition(list):
|
||||
def __getitem__(self, key):
|
||||
try:
|
||||
return super(AutogenDefinition, self).__getitem__(key)
|
||||
except TypeError:
|
||||
for name, value in self:
|
||||
if name == key:
|
||||
return value
|
||||
|
||||
def __contains__(self, key):
|
||||
for name, value in self:
|
||||
if name == key:
|
||||
return True
|
||||
return False
|
||||
|
||||
def get(self, key, default):
|
||||
for name, value in self:
|
||||
if name == key:
|
||||
return value
|
||||
else:
|
||||
return default
|
||||
|
||||
def find_all(self, key):
|
||||
for name, value in self:
|
||||
if name == key:
|
||||
yield value
|
||||
|
||||
class AutogenParser:
|
||||
def __init__(self):
|
||||
self.definitions = AutogenDefinition()
|
||||
self.def_stack = [("", self.definitions)]
|
||||
self.curdef = None
|
||||
self.new_name = None
|
||||
self.cur_path = None
|
||||
self.cur_line = 0
|
||||
|
||||
@staticmethod
|
||||
def is_unquotable_char(c):
|
||||
return (ord(c) in range(ord("!"), ord("~") + 1) and
|
||||
c not in "#,;<=>[\\]`{}?*'\"()")
|
||||
|
||||
@staticmethod
|
||||
def is_value_name_char(c):
|
||||
return c in ":^-_" or c.isalnum()
|
||||
|
||||
def error(self, message):
|
||||
raise AutogenParseError(message, self.cur_file, self.cur_line)
|
||||
|
||||
def read_tokens(self, f):
|
||||
data = f.read()
|
||||
end = len(data)
|
||||
offset = 0
|
||||
while offset < end:
|
||||
while offset < end and data[offset].isspace():
|
||||
if data[offset] == "\n":
|
||||
self.cur_line += 1
|
||||
offset += 1
|
||||
if offset >= end:
|
||||
break
|
||||
c = data[offset]
|
||||
if c == "#":
|
||||
offset += 1
|
||||
try:
|
||||
end_directive = data.index("\n", offset)
|
||||
directive = data[offset:end_directive]
|
||||
offset = end_directive
|
||||
except ValueError:
|
||||
directive = data[offset:]
|
||||
offset = end
|
||||
name, value = directive.split(None, 1)
|
||||
if name == "if":
|
||||
try:
|
||||
end_if = data.index("\n#endif", offset)
|
||||
new_offset = end_if + len("\n#endif")
|
||||
self.cur_line += data[offset:new_offset].count("\n")
|
||||
offset = new_offset
|
||||
except ValueError:
|
||||
self.error("#if without matching #endif")
|
||||
else:
|
||||
self.error("Unhandled directive '#%s'" % name)
|
||||
elif c == "{":
|
||||
yield AutogenToken.lbrace, c
|
||||
offset += 1
|
||||
elif c == "=":
|
||||
yield AutogenToken.equals, c
|
||||
offset += 1
|
||||
elif c == "}":
|
||||
yield AutogenToken.rbrace, c
|
||||
offset += 1
|
||||
elif c == "[":
|
||||
yield AutogenToken.lbracket, c
|
||||
offset += 1
|
||||
elif c == "]":
|
||||
yield AutogenToken.rbracket, c
|
||||
offset += 1
|
||||
elif c == ";":
|
||||
yield AutogenToken.semicolon, c
|
||||
offset += 1
|
||||
elif c == ",":
|
||||
yield AutogenToken.comma, c
|
||||
offset += 1
|
||||
elif c in ("'", '"'):
|
||||
s = []
|
||||
while True:
|
||||
offset += 1
|
||||
if offset >= end:
|
||||
self.error("EOF in quoted string")
|
||||
if data[offset] == "\n":
|
||||
self.cur_line += 1
|
||||
if data[offset] == "\\":
|
||||
offset += 1
|
||||
if offset >= end:
|
||||
self.error("EOF in quoted string")
|
||||
if data[offset] == "\n":
|
||||
self.cur_line += 1
|
||||
# Proper escaping unimplemented; this can be filled
|
||||
# out if needed.
|
||||
s.append("\\")
|
||||
s.append(data[offset])
|
||||
elif data[offset] == c:
|
||||
offset += 1
|
||||
break
|
||||
else:
|
||||
s.append(data[offset])
|
||||
yield AutogenToken.string, "".join(s)
|
||||
elif c == "/":
|
||||
offset += 1
|
||||
if data[offset] == "*":
|
||||
offset += 1
|
||||
try:
|
||||
end_comment = data.index("*/", offset)
|
||||
new_offset = end_comment + len("*/")
|
||||
self.cur_line += data[offset:new_offset].count("\n")
|
||||
offset = new_offset
|
||||
except ValueError:
|
||||
self.error("/* without matching */")
|
||||
elif data[offset] == "/":
|
||||
try:
|
||||
offset = data.index("\n", offset)
|
||||
except ValueError:
|
||||
pass
|
||||
elif (c.isdigit() or
|
||||
(c == "-" and offset < end - 1 and
|
||||
data[offset + 1].isdigit())):
|
||||
end_number = offset + 1
|
||||
while end_number < end and data[end_number].isdigit():
|
||||
end_number += 1
|
||||
yield AutogenToken.number, data[offset:end_number]
|
||||
offset = end_number
|
||||
elif self.is_unquotable_char(c):
|
||||
end_name = offset
|
||||
while (end_name < end and
|
||||
self.is_value_name_char(data[end_name])):
|
||||
end_name += 1
|
||||
if end_name < end and self.is_unquotable_char(data[end_name]):
|
||||
while (end_name < end and
|
||||
self.is_unquotable_char(data[end_name])):
|
||||
end_name += 1
|
||||
yield AutogenToken.other_name, data[offset:end_name]
|
||||
offset = end_name
|
||||
else:
|
||||
s = data[offset:end_name]
|
||||
if s.lower() == "autogen":
|
||||
yield AutogenToken.autogen, s
|
||||
elif s.lower() == "definitions":
|
||||
yield AutogenToken.definitions, s
|
||||
else:
|
||||
yield AutogenToken.var_name, s
|
||||
offset = end_name
|
||||
else:
|
||||
self.error("Invalid input character '%s'" % c)
|
||||
yield AutogenToken.eof, None
|
||||
|
||||
def do_need_name_end(self, token):
|
||||
if len(self.def_stack) > 1:
|
||||
self.error("Definition blocks were left open")
|
||||
|
||||
def do_need_name_var_name(self, token):
|
||||
self.new_name = token
|
||||
|
||||
def do_end_block(self, token):
|
||||
if len(self.def_stack) <= 1:
|
||||
self.error("Too many close braces")
|
||||
new_name, parent_def = self.def_stack.pop()
|
||||
parent_def.append((new_name, self.curdef))
|
||||
self.curdef = parent_def
|
||||
|
||||
def do_empty_val(self, token):
|
||||
self.curdef.append((self.new_name, ""))
|
||||
|
||||
def do_str_value(self, token):
|
||||
self.curdef.append((self.new_name, token))
|
||||
|
||||
def do_start_block(self, token):
|
||||
self.def_stack.append((self.new_name, self.curdef))
|
||||
self.curdef = AutogenDefinition()
|
||||
|
||||
def do_indexed_name(self, token):
|
||||
self.new_name = token
|
||||
|
||||
def read_definitions_file(self, f):
|
||||
self.curdef = self.definitions
|
||||
self.cur_line = 0
|
||||
state = AutogenState.init
|
||||
|
||||
# The following transition table was reduced from the Autogen
|
||||
# documentation:
|
||||
# info -f autogen -n 'Full Syntax'
|
||||
transitions = {
|
||||
AutogenState.init: {
|
||||
AutogenToken.autogen: (AutogenState.need_def, None),
|
||||
},
|
||||
AutogenState.need_def: {
|
||||
AutogenToken.definitions: (AutogenState.need_tpl, None),
|
||||
},
|
||||
AutogenState.need_tpl: {
|
||||
AutogenToken.var_name: (AutogenState.need_semi, None),
|
||||
AutogenToken.other_name: (AutogenState.need_semi, None),
|
||||
AutogenToken.string: (AutogenState.need_semi, None),
|
||||
},
|
||||
AutogenState.need_semi: {
|
||||
AutogenToken.semicolon: (AutogenState.need_name, None),
|
||||
},
|
||||
AutogenState.need_name: {
|
||||
AutogenToken.autogen: (AutogenState.need_def, None),
|
||||
AutogenToken.eof: (AutogenState.done, self.do_need_name_end),
|
||||
AutogenToken.var_name: (
|
||||
AutogenState.have_name, self.do_need_name_var_name),
|
||||
AutogenToken.rbrace: (
|
||||
AutogenState.have_value, self.do_end_block),
|
||||
},
|
||||
AutogenState.have_name: {
|
||||
AutogenToken.semicolon: (
|
||||
AutogenState.need_name, self.do_empty_val),
|
||||
AutogenToken.equals: (AutogenState.need_value, None),
|
||||
AutogenToken.lbracket: (AutogenState.need_idx, None),
|
||||
},
|
||||
AutogenState.need_value: {
|
||||
AutogenToken.var_name: (
|
||||
AutogenState.have_value, self.do_str_value),
|
||||
AutogenToken.other_name: (
|
||||
AutogenState.have_value, self.do_str_value),
|
||||
AutogenToken.string: (
|
||||
AutogenState.have_value, self.do_str_value),
|
||||
AutogenToken.number: (
|
||||
AutogenState.have_value, self.do_str_value),
|
||||
AutogenToken.lbrace: (
|
||||
AutogenState.need_name, self.do_start_block),
|
||||
},
|
||||
AutogenState.need_idx: {
|
||||
AutogenToken.var_name: (
|
||||
AutogenState.need_rbracket, self.do_indexed_name),
|
||||
AutogenToken.number: (
|
||||
AutogenState.need_rbracket, self.do_indexed_name),
|
||||
},
|
||||
AutogenState.need_rbracket: {
|
||||
AutogenToken.rbracket: (AutogenState.indx_name, None),
|
||||
},
|
||||
AutogenState.indx_name: {
|
||||
AutogenToken.semicolon: (
|
||||
AutogenState.need_name, self.do_empty_val),
|
||||
AutogenToken.equals: (AutogenState.need_value, None),
|
||||
},
|
||||
AutogenState.have_value: {
|
||||
AutogenToken.semicolon: (AutogenState.need_name, None),
|
||||
AutogenToken.comma: (AutogenState.need_value, None),
|
||||
},
|
||||
}
|
||||
|
||||
for code, token in self.read_tokens(f):
|
||||
if code in transitions[state]:
|
||||
state, handler = transitions[state][code]
|
||||
if handler is not None:
|
||||
handler(token)
|
||||
else:
|
||||
self.error(
|
||||
"Parse error in state %s: unexpected token '%s'" % (
|
||||
state, token))
|
||||
if state == AutogenState.done:
|
||||
break
|
||||
|
||||
def read_definitions(self, path):
|
||||
self.cur_file = path
|
||||
with open(path) as f:
|
||||
self.read_definitions_file(f)
|
||||
|
||||
defparser = AutogenParser()
|
||||
|
||||
#
|
||||
# Output
|
||||
#
|
||||
|
||||
outputs = {}
|
||||
|
||||
def output(s, section=''):
|
||||
if s == "":
|
||||
return
|
||||
outputs.setdefault(section, [])
|
||||
outputs[section].append(s)
|
||||
|
||||
def write_output(section=''):
|
||||
for s in outputs.get(section, []):
|
||||
print(s, end='')
|
||||
|
||||
#
|
||||
# Global variables
|
||||
#
|
||||
|
||||
def gvar_add(var, value):
|
||||
output(var + " += " + value + "\n")
|
||||
|
||||
#
|
||||
# Per PROGRAM/SCRIPT variables
|
||||
#
|
||||
|
||||
seen_vars = set()
|
||||
|
||||
def vars_init(defn, *var_list):
|
||||
name = defn['name']
|
||||
|
||||
if name not in seen_target and name not in seen_vars:
|
||||
for var in var_list:
|
||||
output(var + " = \n", section='decl')
|
||||
seen_vars.add(name)
|
||||
|
||||
def var_set(var, value):
|
||||
output(var + " = " + value + "\n")
|
||||
|
||||
def var_add(var, value):
|
||||
output(var + " += " + value + "\n")
|
||||
|
||||
#
|
||||
# Variable names and rules
|
||||
#
|
||||
|
||||
canonical_name_re = re.compile(r'[^0-9A-Za-z@_]')
|
||||
canonical_name_suffix = ""
|
||||
|
||||
def set_canonical_name_suffix(suffix):
|
||||
global canonical_name_suffix
|
||||
canonical_name_suffix = suffix
|
||||
|
||||
def cname(defn):
|
||||
return canonical_name_re.sub('_', defn['name'] + canonical_name_suffix)
|
||||
|
||||
def rule(target, source, cmd):
|
||||
if cmd[0] == "\n":
|
||||
output("\n" + target + ": " + source + cmd.replace("\n", "\n\t") + "\n")
|
||||
else:
|
||||
output("\n" + target + ": " + source + "\n\t" + cmd.replace("\n", "\n\t") + "\n")
|
||||
|
||||
#
|
||||
# Handle keys with platform names as values, for example:
|
||||
#
|
||||
# kernel = {
|
||||
# nostrip = emu;
|
||||
# ...
|
||||
# }
|
||||
#
|
||||
def platform_tagged(defn, platform, tag):
|
||||
for value in defn.find_all(tag):
|
||||
for group in RMAP[platform]:
|
||||
if value == group:
|
||||
return True
|
||||
return False
|
||||
|
||||
def if_platform_tagged(defn, platform, tag, snippet_if, snippet_else=None):
|
||||
if platform_tagged(defn, platform, tag):
|
||||
return snippet_if
|
||||
elif snippet_else is not None:
|
||||
return snippet_else
|
||||
|
||||
#
|
||||
# Handle tagged values
|
||||
#
|
||||
# module = {
|
||||
# extra_dist = ...
|
||||
# extra_dist = ...
|
||||
# ...
|
||||
# };
|
||||
#
|
||||
def foreach_value(defn, tag, closure):
|
||||
r = []
|
||||
for value in defn.find_all(tag):
|
||||
r.append(closure(value))
|
||||
return ''.join(r)
|
||||
|
||||
#
|
||||
# Handle best matched values for a platform, for example:
|
||||
#
|
||||
# module = {
|
||||
# cflags = '-Wall';
|
||||
# emu_cflags = '-Wall -DGRUB_EMU=1';
|
||||
# ...
|
||||
# }
|
||||
#
|
||||
def foreach_platform_specific_value(defn, platform, suffix, nonetag, closure):
|
||||
r = []
|
||||
for group in RMAP[platform]:
|
||||
values = list(defn.find_all(group + suffix))
|
||||
if values:
|
||||
for value in values:
|
||||
r.append(closure(value))
|
||||
break
|
||||
else:
|
||||
for value in defn.find_all(nonetag):
|
||||
r.append(closure(value))
|
||||
return ''.join(r)
|
||||
|
||||
#
|
||||
# Handle values from sum of all groups for a platform, for example:
|
||||
#
|
||||
# module = {
|
||||
# common = kern/misc.c;
|
||||
# emu = kern/emu/misc.c;
|
||||
# ...
|
||||
# }
|
||||
#
|
||||
def foreach_platform_value(defn, platform, suffix, closure):
|
||||
r = []
|
||||
for group in RMAP[platform]:
|
||||
for value in defn.find_all(group + suffix):
|
||||
r.append(closure(value))
|
||||
return ''.join(r)
|
||||
|
||||
def platform_conditional(platform, closure):
|
||||
output("\nif COND_" + platform + "\n")
|
||||
closure(platform)
|
||||
output("endif\n")
|
||||
|
||||
#
|
||||
# Handle guarding with platform-specific "enable" keys, for example:
|
||||
#
|
||||
# module = {
|
||||
# name = pci;
|
||||
# noemu = bus/pci.c;
|
||||
# emu = bus/emu/pci.c;
|
||||
# emu = commands/lspci.c;
|
||||
#
|
||||
# enable = emu;
|
||||
# enable = i386_pc;
|
||||
# enable = x86_efi;
|
||||
# enable = i386_ieee1275;
|
||||
# enable = i386_coreboot;
|
||||
# };
|
||||
#
|
||||
def foreach_enabled_platform(defn, closure):
|
||||
if 'enable' in defn:
|
||||
for platform in GRUB_PLATFORMS:
|
||||
if platform_tagged(defn, platform, "enable"):
|
||||
platform_conditional(platform, closure)
|
||||
else:
|
||||
for platform in GRUB_PLATFORMS:
|
||||
platform_conditional(platform, closure)
|
||||
|
||||
#
|
||||
# Handle guarding with platform-specific automake conditionals, for example:
|
||||
#
|
||||
# module = {
|
||||
# name = usb;
|
||||
# common = bus/usb/usb.c;
|
||||
# noemu = bus/usb/usbtrans.c;
|
||||
# noemu = bus/usb/usbhub.c;
|
||||
# enable = emu;
|
||||
# enable = i386;
|
||||
# enable = mips_loongson;
|
||||
# emu_condition = COND_GRUB_EMU_SDL;
|
||||
# };
|
||||
#
|
||||
def under_platform_specific_conditionals(defn, platform, closure):
|
||||
output(foreach_platform_specific_value(defn, platform, "_condition", "condition", lambda cond: "if " + cond + "\n"))
|
||||
closure(defn, platform)
|
||||
output(foreach_platform_specific_value(defn, platform, "_condition", "condition", lambda cond: "endif " + cond + "\n"))
|
||||
|
||||
def platform_specific_values(defn, platform, suffix, nonetag):
|
||||
return foreach_platform_specific_value(defn, platform, suffix, nonetag,
|
||||
lambda value: value + " ")
|
||||
|
||||
def platform_values(defn, platform, suffix):
|
||||
return foreach_platform_value(defn, platform, suffix, lambda value: value + " ")
|
||||
|
||||
def extra_dist(defn):
|
||||
return foreach_value(defn, "extra_dist", lambda value: value + " ")
|
||||
|
||||
def platform_sources(defn, p): return platform_values(defn, p, "")
|
||||
def platform_nodist_sources(defn, p): return platform_values(defn, p, "_nodist")
|
||||
|
||||
def platform_startup(defn, p): return platform_specific_values(defn, p, "_startup", "startup")
|
||||
def platform_ldadd(defn, p): return platform_specific_values(defn, p, "_ldadd", "ldadd")
|
||||
def platform_dependencies(defn, p): return platform_specific_values(defn, p, "_dependencies", "dependencies")
|
||||
def platform_cflags(defn, p): return platform_specific_values(defn, p, "_cflags", "cflags")
|
||||
def platform_ldflags(defn, p): return platform_specific_values(defn, p, "_ldflags", "ldflags")
|
||||
def platform_cppflags(defn, p): return platform_specific_values(defn, p, "_cppflags", "cppflags")
|
||||
def platform_ccasflags(defn, p): return platform_specific_values(defn, p, "_ccasflags", "ccasflags")
|
||||
def platform_stripflags(defn, p): return platform_specific_values(defn, p, "_stripflags", "stripflags")
|
||||
def platform_objcopyflags(defn, p): return platform_specific_values(defn, p, "_objcopyflags", "objcopyflags")
|
||||
|
||||
#
|
||||
# Emit snippet only the first time through for the current name.
|
||||
#
|
||||
seen_target = set()
|
||||
|
||||
def first_time(defn, snippet):
|
||||
if defn['name'] not in seen_target:
|
||||
return snippet
|
||||
return ''
|
||||
|
||||
def is_platform_independent(defn):
|
||||
if 'enable' in defn:
|
||||
return False
|
||||
for suffix in [ "", "_nodist" ]:
|
||||
template = platform_values(defn, GRUB_PLATFORMS[0], suffix)
|
||||
for platform in GRUB_PLATFORMS[1:]:
|
||||
if template != platform_values(defn, platform, suffix):
|
||||
return False
|
||||
|
||||
for suffix in [ "startup", "ldadd", "dependencies", "cflags", "ldflags", "cppflags", "ccasflags", "stripflags", "objcopyflags", "condition" ]:
|
||||
template = platform_specific_values(defn, GRUB_PLATFORMS[0], "_" + suffix, suffix)
|
||||
for platform in GRUB_PLATFORMS[1:]:
|
||||
if template != platform_specific_values(defn, platform, "_" + suffix, suffix):
|
||||
return False
|
||||
for tag in [ "nostrip" ]:
|
||||
template = platform_tagged(defn, GRUB_PLATFORMS[0], tag)
|
||||
for platform in GRUB_PLATFORMS[1:]:
|
||||
if template != platform_tagged(defn, platform, tag):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def module(defn, platform):
|
||||
name = defn['name']
|
||||
set_canonical_name_suffix(".module")
|
||||
|
||||
gvar_add("platform_PROGRAMS", name + ".module")
|
||||
gvar_add("MODULE_FILES", name + ".module$(EXEEXT)")
|
||||
|
||||
var_set(cname(defn) + "_SOURCES", platform_sources(defn, platform) + " ## platform sources")
|
||||
var_set("nodist_" + cname(defn) + "_SOURCES", platform_nodist_sources(defn, platform) + " ## platform nodist sources")
|
||||
var_set(cname(defn) + "_LDADD", platform_ldadd(defn, platform))
|
||||
var_set(cname(defn) + "_CFLAGS", "$(AM_CFLAGS) $(CFLAGS_MODULE) " + platform_cflags(defn, platform))
|
||||
var_set(cname(defn) + "_LDFLAGS", "$(AM_LDFLAGS) $(LDFLAGS_MODULE) " + platform_ldflags(defn, platform))
|
||||
var_set(cname(defn) + "_CPPFLAGS", "$(AM_CPPFLAGS) $(CPPFLAGS_MODULE) " + platform_cppflags(defn, platform))
|
||||
var_set(cname(defn) + "_CCASFLAGS", "$(AM_CCASFLAGS) $(CCASFLAGS_MODULE) " + platform_ccasflags(defn, platform))
|
||||
var_set(cname(defn) + "_DEPENDENCIES", "$(TARGET_OBJ2ELF) " + platform_dependencies(defn, platform))
|
||||
|
||||
gvar_add("dist_noinst_DATA", extra_dist(defn))
|
||||
gvar_add("BUILT_SOURCES", "$(nodist_" + cname(defn) + "_SOURCES)")
|
||||
gvar_add("CLEANFILES", "$(nodist_" + cname(defn) + "_SOURCES)")
|
||||
|
||||
gvar_add("MOD_FILES", name + ".mod")
|
||||
gvar_add("MARKER_FILES", name + ".marker")
|
||||
gvar_add("CLEANFILES", name + ".marker")
|
||||
output("""
|
||||
""" + name + """.marker: $(""" + cname(defn) + """_SOURCES) $(nodist_""" + cname(defn) + """_SOURCES)
|
||||
$(TARGET_CPP) -DGRUB_LST_GENERATOR $(CPPFLAGS_MARKER) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(""" + cname(defn) + """_CPPFLAGS) $(CPPFLAGS) $^ > $@.new || (rm -f $@; exit 1)
|
||||
grep 'MARKER' $@.new > $@; rm -f $@.new
|
||||
""")
|
||||
|
||||
def kernel(defn, platform):
|
||||
name = defn['name']
|
||||
set_canonical_name_suffix(".exec")
|
||||
gvar_add("platform_PROGRAMS", name + ".exec")
|
||||
var_set(cname(defn) + "_SOURCES", platform_startup(defn, platform))
|
||||
var_add(cname(defn) + "_SOURCES", platform_sources(defn, platform))
|
||||
var_set("nodist_" + cname(defn) + "_SOURCES", platform_nodist_sources(defn, platform) + " ## platform nodist sources")
|
||||
var_set(cname(defn) + "_LDADD", platform_ldadd(defn, platform))
|
||||
var_set(cname(defn) + "_CFLAGS", "$(AM_CFLAGS) $(CFLAGS_KERNEL) " + platform_cflags(defn, platform))
|
||||
var_set(cname(defn) + "_LDFLAGS", "$(AM_LDFLAGS) $(LDFLAGS_KERNEL) " + platform_ldflags(defn, platform))
|
||||
var_set(cname(defn) + "_CPPFLAGS", "$(AM_CPPFLAGS) $(CPPFLAGS_KERNEL) " + platform_cppflags(defn, platform))
|
||||
var_set(cname(defn) + "_CCASFLAGS", "$(AM_CCASFLAGS) $(CCASFLAGS_KERNEL) " + platform_ccasflags(defn, platform))
|
||||
var_set(cname(defn) + "_STRIPFLAGS", "$(AM_STRIPFLAGS) $(STRIPFLAGS_KERNEL) " + platform_stripflags(defn, platform))
|
||||
var_set(cname(defn) + "_DEPENDENCIES", "$(TARGET_OBJ2ELF)")
|
||||
|
||||
gvar_add("dist_noinst_DATA", extra_dist(defn))
|
||||
gvar_add("BUILT_SOURCES", "$(nodist_" + cname(defn) + "_SOURCES)")
|
||||
gvar_add("CLEANFILES", "$(nodist_" + cname(defn) + "_SOURCES)")
|
||||
|
||||
gvar_add("platform_DATA", name + ".img")
|
||||
gvar_add("CLEANFILES", name + ".img")
|
||||
rule(name + ".img", name + ".exec$(EXEEXT)",
|
||||
if_platform_tagged(defn, platform, "nostrip",
|
||||
"""if test x$(TARGET_APPLE_LINKER) = x1; then \
|
||||
$(TARGET_OBJCONV) -f$(TARGET_MODULE_FORMAT) -nr:_grub_mod_init:grub_mod_init -nr:_grub_mod_fini:grub_mod_fini -ed2022 -wd1106 -nu -nd $< $@; \
|
||||
elif test ! -z '$(TARGET_OBJ2ELF)'; then \
|
||||
$(TARGET_OBJ2ELF) $< $@ || (rm -f $@; exit 1); \
|
||||
else cp $< $@; fi""",
|
||||
"""if test x$(TARGET_APPLE_LINKER) = x1; then \
|
||||
$(TARGET_STRIP) -S -x $(""" + cname(defn) + """) -o $@.bin $<; \
|
||||
$(TARGET_OBJCONV) -f$(TARGET_MODULE_FORMAT) -nr:_grub_mod_init:grub_mod_init -nr:_grub_mod_fini:grub_mod_fini -ed2022 -ed2016 -wd1106 -nu -nd $@.bin $@; \
|
||||
rm -f $@.bin; \
|
||||
elif test ! -z '$(TARGET_OBJ2ELF)'; then \
|
||||
""" + "$(TARGET_STRIP) $(" + cname(defn) + "_STRIPFLAGS) -o $@.bin $< && \
|
||||
$(TARGET_OBJ2ELF) $@.bin $@ || (rm -f $@; rm -f $@.bin; exit 1); \
|
||||
rm -f $@.bin; \
|
||||
else """ + "$(TARGET_STRIP) $(" + cname(defn) + "_STRIPFLAGS) -o $@ $<; \
|
||||
fi"""))
|
||||
|
||||
def image(defn, platform):
|
||||
name = defn['name']
|
||||
set_canonical_name_suffix(".image")
|
||||
gvar_add("platform_PROGRAMS", name + ".image")
|
||||
var_set(cname(defn) + "_SOURCES", platform_sources(defn, platform))
|
||||
var_set("nodist_" + cname(defn) + "_SOURCES", platform_nodist_sources(defn, platform) + "## platform nodist sources")
|
||||
var_set(cname(defn) + "_LDADD", platform_ldadd(defn, platform))
|
||||
var_set(cname(defn) + "_CFLAGS", "$(AM_CFLAGS) $(CFLAGS_IMAGE) " + platform_cflags(defn, platform))
|
||||
var_set(cname(defn) + "_LDFLAGS", "$(AM_LDFLAGS) $(LDFLAGS_IMAGE) " + platform_ldflags(defn, platform))
|
||||
var_set(cname(defn) + "_CPPFLAGS", "$(AM_CPPFLAGS) $(CPPFLAGS_IMAGE) " + platform_cppflags(defn, platform))
|
||||
var_set(cname(defn) + "_CCASFLAGS", "$(AM_CCASFLAGS) $(CCASFLAGS_IMAGE) " + platform_ccasflags(defn, platform))
|
||||
var_set(cname(defn) + "_OBJCOPYFLAGS", "$(OBJCOPYFLAGS_IMAGE) " + platform_objcopyflags(defn, platform))
|
||||
# var_set(cname(defn) + "_DEPENDENCIES", platform_dependencies(defn, platform) + " " + platform_ldadd(defn, platform))
|
||||
|
||||
gvar_add("dist_noinst_DATA", extra_dist(defn))
|
||||
gvar_add("BUILT_SOURCES", "$(nodist_" + cname(defn) + "_SOURCES)")
|
||||
gvar_add("CLEANFILES", "$(nodist_" + cname(defn) + "_SOURCES)")
|
||||
|
||||
gvar_add("platform_DATA", name + ".img")
|
||||
gvar_add("CLEANFILES", name + ".img")
|
||||
rule(name + ".img", name + ".image$(EXEEXT)", """
|
||||
if test x$(TARGET_APPLE_LINKER) = x1; then \
|
||||
$(MACHO2IMG) $< $@; \
|
||||
else \
|
||||
$(TARGET_OBJCOPY) $(""" + cname(defn) + """_OBJCOPYFLAGS) --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .MIPS.abiflags -R .reginfo -R .rel.dyn -R .note.gnu.gold-version -R .ARM.exidx $< $@; \
|
||||
fi
|
||||
""")
|
||||
|
||||
def library(defn, platform):
|
||||
name = defn['name']
|
||||
set_canonical_name_suffix("")
|
||||
|
||||
vars_init(defn,
|
||||
cname(defn) + "_SOURCES",
|
||||
"nodist_" + cname(defn) + "_SOURCES",
|
||||
cname(defn) + "_CFLAGS",
|
||||
cname(defn) + "_CPPFLAGS",
|
||||
cname(defn) + "_CCASFLAGS")
|
||||
# cname(defn) + "_DEPENDENCIES")
|
||||
|
||||
if name not in seen_target:
|
||||
gvar_add("noinst_LIBRARIES", name)
|
||||
var_add(cname(defn) + "_SOURCES", platform_sources(defn, platform))
|
||||
var_add("nodist_" + cname(defn) + "_SOURCES", platform_nodist_sources(defn, platform))
|
||||
var_add(cname(defn) + "_CFLAGS", first_time(defn, "$(AM_CFLAGS) $(CFLAGS_LIBRARY) ") + platform_cflags(defn, platform))
|
||||
var_add(cname(defn) + "_CPPFLAGS", first_time(defn, "$(AM_CPPFLAGS) $(CPPFLAGS_LIBRARY) ") + platform_cppflags(defn, platform))
|
||||
var_add(cname(defn) + "_CCASFLAGS", first_time(defn, "$(AM_CCASFLAGS) $(CCASFLAGS_LIBRARY) ") + platform_ccasflags(defn, platform))
|
||||
# var_add(cname(defn) + "_DEPENDENCIES", platform_dependencies(defn, platform) + " " + platform_ldadd(defn, platform))
|
||||
|
||||
gvar_add("dist_noinst_DATA", extra_dist(defn))
|
||||
if name not in seen_target:
|
||||
gvar_add("BUILT_SOURCES", "$(nodist_" + cname(defn) + "_SOURCES)")
|
||||
gvar_add("CLEANFILES", "$(nodist_" + cname(defn) + "_SOURCES)")
|
||||
|
||||
def installdir(defn, default="bin"):
|
||||
return defn.get('installdir', default)
|
||||
|
||||
def manpage(defn, adddeps):
|
||||
name = defn['name']
|
||||
mansection = defn['mansection']
|
||||
|
||||
output("if COND_MAN_PAGES\n")
|
||||
gvar_add("man_MANS", name + "." + mansection)
|
||||
rule(name + "." + mansection, name + " " + adddeps, """
|
||||
chmod a+x """ + name + """
|
||||
PATH=$(builddir):$$PATH pkgdatadir=$(builddir) $(HELP2MAN) --section=""" + mansection + """ -i $(top_srcdir)/docs/man/""" + name + """.h2m -o $@ """ + name + """
|
||||
""")
|
||||
gvar_add("CLEANFILES", name + "." + mansection)
|
||||
output("endif\n")
|
||||
|
||||
def program(defn, platform, test=False):
|
||||
name = defn['name']
|
||||
set_canonical_name_suffix("")
|
||||
|
||||
if 'testcase' in defn:
|
||||
gvar_add("check_PROGRAMS", name)
|
||||
gvar_add("TESTS", name)
|
||||
else:
|
||||
var_add(installdir(defn) + "_PROGRAMS", name)
|
||||
if 'mansection' in defn:
|
||||
manpage(defn, "")
|
||||
|
||||
var_set(cname(defn) + "_SOURCES", platform_sources(defn, platform))
|
||||
var_set("nodist_" + cname(defn) + "_SOURCES", platform_nodist_sources(defn, platform))
|
||||
var_set(cname(defn) + "_LDADD", platform_ldadd(defn, platform))
|
||||
var_set(cname(defn) + "_CFLAGS", "$(AM_CFLAGS) $(CFLAGS_PROGRAM) " + platform_cflags(defn, platform))
|
||||
var_set(cname(defn) + "_LDFLAGS", "$(AM_LDFLAGS) $(LDFLAGS_PROGRAM) " + platform_ldflags(defn, platform))
|
||||
var_set(cname(defn) + "_CPPFLAGS", "$(AM_CPPFLAGS) $(CPPFLAGS_PROGRAM) " + platform_cppflags(defn, platform))
|
||||
var_set(cname(defn) + "_CCASFLAGS", "$(AM_CCASFLAGS) $(CCASFLAGS_PROGRAM) " + platform_ccasflags(defn, platform))
|
||||
# var_set(cname(defn) + "_DEPENDENCIES", platform_dependencies(defn, platform) + " " + platform_ldadd(defn, platform))
|
||||
|
||||
gvar_add("dist_noinst_DATA", extra_dist(defn))
|
||||
gvar_add("BUILT_SOURCES", "$(nodist_" + cname(defn) + "_SOURCES)")
|
||||
gvar_add("CLEANFILES", "$(nodist_" + cname(defn) + "_SOURCES)")
|
||||
|
||||
def data(defn, platform):
|
||||
var_add("dist_" + installdir(defn) + "_DATA", platform_sources(defn, platform))
|
||||
gvar_add("dist_noinst_DATA", extra_dist(defn))
|
||||
|
||||
def transform_data(defn, platform):
|
||||
name = defn['name']
|
||||
|
||||
var_add(installdir(defn) + "_DATA", name)
|
||||
|
||||
rule(name, "$(top_builddir)/config.status " + platform_sources(defn, platform) + platform_dependencies(defn, platform), """
|
||||
(for x in """ + platform_sources(defn, platform) + """; do cat $(srcdir)/"$$x"; done) | $(top_builddir)/config.status --file=$@:-
|
||||
chmod a+x """ + name + """
|
||||
""")
|
||||
|
||||
gvar_add("CLEANFILES", name)
|
||||
gvar_add("EXTRA_DIST", extra_dist(defn))
|
||||
gvar_add("dist_noinst_DATA", platform_sources(defn, platform))
|
||||
|
||||
def script(defn, platform):
|
||||
name = defn['name']
|
||||
|
||||
if 'testcase' in defn:
|
||||
gvar_add("check_SCRIPTS", name)
|
||||
gvar_add ("TESTS", name)
|
||||
else:
|
||||
var_add(installdir(defn) + "_SCRIPTS", name)
|
||||
if 'mansection' in defn:
|
||||
manpage(defn, "grub-mkconfig_lib")
|
||||
|
||||
rule(name, "$(top_builddir)/config.status " + platform_sources(defn, platform) + platform_dependencies(defn, platform), """
|
||||
(for x in """ + platform_sources(defn, platform) + """; do cat $(srcdir)/"$$x"; done) | $(top_builddir)/config.status --file=$@:-
|
||||
chmod a+x """ + name + """
|
||||
""")
|
||||
|
||||
gvar_add("CLEANFILES", name)
|
||||
gvar_add("EXTRA_DIST", extra_dist(defn))
|
||||
gvar_add("dist_noinst_DATA", platform_sources(defn, platform))
|
||||
|
||||
def rules(target, closure):
|
||||
seen_target.clear()
|
||||
seen_vars.clear()
|
||||
|
||||
for defn in defparser.definitions.find_all(target):
|
||||
if is_platform_independent(defn):
|
||||
under_platform_specific_conditionals(defn, GRUB_PLATFORMS[0], closure)
|
||||
else:
|
||||
foreach_enabled_platform(
|
||||
defn,
|
||||
lambda p: under_platform_specific_conditionals(defn, p, closure))
|
||||
# Remember that we've seen this target.
|
||||
seen_target.add(defn['name'])
|
||||
|
||||
parser = OptionParser(usage="%prog DEFINITION-FILES")
|
||||
_, args = parser.parse_args()
|
||||
|
||||
for arg in args:
|
||||
defparser.read_definitions(arg)
|
||||
|
||||
rules("module", module)
|
||||
rules("kernel", kernel)
|
||||
rules("image", image)
|
||||
rules("library", library)
|
||||
rules("program", program)
|
||||
rules("script", script)
|
||||
rules("data", data)
|
||||
rules("transform_data", transform_data)
|
||||
|
||||
write_output(section='decl')
|
||||
write_output()
|
507
GRUB2/MOD_SRC/grub-2.04/grub-core/Makefile.am
Normal file
507
GRUB2/MOD_SRC/grub-2.04/grub-core/Makefile.am
Normal file
@ -0,0 +1,507 @@
|
||||
AUTOMAKE_OPTIONS = subdir-objects -Wno-portability
|
||||
|
||||
DEPDIR=.deps-core
|
||||
|
||||
include $(top_srcdir)/conf/Makefile.common
|
||||
|
||||
CC=$(TARGET_CC)
|
||||
CPP=$(TARGET_CC)
|
||||
CCAS=$(TARGET_CC)
|
||||
RANLIB=$(TARGET_RANLIB)
|
||||
STRIP=$(TARGET_STRIP)
|
||||
|
||||
MACHO2IMG=$(top_builddir)/grub-macho2img
|
||||
|
||||
AM_CFLAGS = $(TARGET_CFLAGS)
|
||||
AM_LDFLAGS = $(TARGET_LDFLAGS)
|
||||
AM_CPPFLAGS = $(TARGET_CPPFLAGS) $(CPPFLAGS_DEFAULT)
|
||||
AM_CCASFLAGS = $(TARGET_CCASFLAGS) $(CCASFLAGS_DEFAULT)
|
||||
|
||||
CFLAGS_PROGRAM += $(CFLAGS_PLATFORM)
|
||||
LDFLAGS_PROGRAM += $(LDFLAGS_PLATFORM)
|
||||
CPPFLAGS_PROGRAM += $(CPPFLAGS_PLATFORM)
|
||||
CCASFLAGS_PROGRAM += $(CCASFLAGS_PLATFORM)
|
||||
|
||||
CFLAGS_LIBRARY += $(CFLAGS_PLATFORM) -fno-builtin
|
||||
CPPFLAGS_LIBRARY += $(CPPFLAGS_PLATFORM)
|
||||
CCASFLAGS_LIBRARY += $(CCASFLAGS_PLATFORM)
|
||||
|
||||
build-grub-pep2elf$(BUILD_EXEEXT): $(top_srcdir)/util/grub-pe2elf.c $(top_srcdir)/grub-core/kern/emu/misc.c $(top_srcdir)/util/misc.c
|
||||
$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_BUILD=1 -DGRUB_TARGET_WORDSIZE=64 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-pep2elf\" $^
|
||||
CLEANFILES += build-grub-pep2elf$(BUILD_EXEEXT)
|
||||
|
||||
build-grub-pe2elf$(BUILD_EXEEXT): $(top_srcdir)/util/grub-pe2elf.c $(top_srcdir)/grub-core/kern/emu/misc.c $(top_srcdir)/util/misc.c
|
||||
$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_BUILD=1 -DGRUB_TARGET_WORDSIZE=32 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-pe2elf\" $^
|
||||
CLEANFILES += build-grub-pe2elf$(BUILD_EXEEXT)
|
||||
|
||||
# gentrigtables
|
||||
gentrigtables$(BUILD_EXEEXT): gentrigtables.c
|
||||
$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) $< $(BUILD_LIBM)
|
||||
CLEANFILES += gentrigtables$(BUILD_EXEEXT)
|
||||
|
||||
build-grub-module-verifier$(BUILD_EXEEXT): $(top_srcdir)/util/grub-module-verifier.c $(top_srcdir)/util/grub-module-verifier32.c $(top_srcdir)/util/grub-module-verifier64.c $(top_srcdir)/grub-core/kern/emu/misc.c $(top_srcdir)/util/misc.c
|
||||
$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_BUILD=1 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-module-verifier\" $^
|
||||
CLEANFILES += build-grub-module-verifier$(BUILD_EXEEXT)
|
||||
|
||||
# trigtables.c
|
||||
trigtables.c: gentrigtables$(BUILD_EXEEXT) gentrigtables.c $(top_srcdir)/configure.ac
|
||||
./gentrigtables$(BUILD_EXEEXT) > $@
|
||||
CLEANFILES += trigtables.c
|
||||
|
||||
# XXX Use Automake's LEX & YACC support
|
||||
grub_script.tab.h: script/parser.y
|
||||
$(YACC) -d -p grub_script_yy -b grub_script $<
|
||||
grub_script.tab.c: grub_script.tab.h
|
||||
CLEANFILES += grub_script.tab.c grub_script.tab.h
|
||||
|
||||
# For the lexer.
|
||||
grub_script.yy.h: script/yylex.l
|
||||
$(LEX) -o grub_script.yy.c --header-file=grub_script.yy.h $<
|
||||
grub_script.yy.c: grub_script.yy.h
|
||||
|
||||
rs_decoder.h: $(srcdir)/lib/reed_solomon.c
|
||||
$(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) -Os -I$(top_builddir) -S -DSTANDALONE -o $@ $< -g0 -mregparm=3 -ffreestanding
|
||||
|
||||
CLEANFILES += grub_script.yy.c grub_script.yy.h
|
||||
|
||||
include $(srcdir)/Makefile.core.am
|
||||
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/cache.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/command.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/device.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/disk.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/dl.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/env.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/env_private.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/err.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/file.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/fs.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i18n.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/kernel.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/list.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/misc.h
|
||||
if COND_emu
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/compiler-rt-emu.h
|
||||
else
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/compiler-rt.h
|
||||
endif
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/parser.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/partition.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm_private.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/net.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h
|
||||
|
||||
if COND_i386_pc
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/pxe.h
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/int.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h
|
||||
endif
|
||||
|
||||
if COND_i386_xen_pvh
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/int.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/xen.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/xen/hypercall.h
|
||||
endif
|
||||
|
||||
if COND_i386_efi
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pmtimer.h
|
||||
endif
|
||||
|
||||
if COND_i386_coreboot
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/coreboot/lbio.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video_fb.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/gfxterm.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/font.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bufio.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
|
||||
endif
|
||||
|
||||
if COND_i386_multiboot
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
|
||||
endif
|
||||
|
||||
if COND_i386_qemu
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h
|
||||
endif
|
||||
|
||||
if COND_i386_ieee1275
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h
|
||||
endif
|
||||
|
||||
if COND_i386_xen
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/xen.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/xen/hypercall.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h
|
||||
endif
|
||||
|
||||
if COND_x86_64_xen
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/xen.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/x86_64/xen/hypercall.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h
|
||||
endif
|
||||
|
||||
if COND_x86_64_efi
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pmtimer.h
|
||||
endif
|
||||
|
||||
if COND_ia64_efi
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
|
||||
endif
|
||||
|
||||
if COND_mips
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/cpu/kernel.h
|
||||
endif
|
||||
|
||||
if COND_mips_arc
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arc/arc.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
|
||||
endif
|
||||
|
||||
if COND_mips_qemu_mips
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/keyboard_layouts.h
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/serial.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
|
||||
endif
|
||||
|
||||
if COND_mips_loongson
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/keyboard_layouts.h
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/time.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video_fb.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/gfxterm.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/font.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bufio.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/cs5536.h
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/pci.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/serial.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
|
||||
endif
|
||||
|
||||
if COND_mips_qemu_mips
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
|
||||
endif
|
||||
|
||||
if COND_mips64_efi
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/loongson.h
|
||||
endif
|
||||
|
||||
if COND_powerpc_ieee1275
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
|
||||
endif
|
||||
|
||||
if COND_sparc64_ieee1275
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sparc64/ieee1275/ieee1275.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
|
||||
endif
|
||||
|
||||
if COND_arm_uboot
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/uboot/uboot.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/uboot/disk.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/system.h
|
||||
endif
|
||||
|
||||
if COND_arm_coreboot
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/keyboard_layouts.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/system.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video_fb.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/gfxterm.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/font.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bufio.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/fdt.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/dma.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/coreboot/kernel.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/fdtbus.h
|
||||
endif
|
||||
|
||||
if COND_arm_efi
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/system.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
|
||||
endif
|
||||
|
||||
if COND_arm64_efi
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
|
||||
endif
|
||||
|
||||
if COND_riscv32_efi
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
|
||||
endif
|
||||
|
||||
if COND_riscv64_efi
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
|
||||
endif
|
||||
|
||||
if COND_emu
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/datetime.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/misc.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/net.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/hostdisk.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/hostfile.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
||||
if COND_GRUB_EMU_SDL
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sdl.h
|
||||
endif
|
||||
if COND_GRUB_EMU_PCI
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libpciaccess.h
|
||||
endif
|
||||
endif
|
||||
|
||||
symlist.h: $(top_builddir)/config.h $(KERNEL_HEADER_FILES)
|
||||
@list='$^'; \
|
||||
for p in $$list; do \
|
||||
echo "#include <$$p>" >> $@ || (rm -f $@; exit 1); \
|
||||
done
|
||||
CLEANFILES += symlist.h
|
||||
BUILT_SOURCES += symlist.h
|
||||
|
||||
symlist.c: symlist.h gensymlist.sh
|
||||
$(TARGET_CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS_KERNEL) $(CPPFLAGS) -DGRUB_SYMBOL_GENERATOR=1 symlist.h > symlist.p || (rm -f symlist.p; exit 1)
|
||||
cat symlist.p | $(SHELL) $(srcdir)/gensymlist.sh $(top_builddir)/config.h $(KERNEL_HEADER_FILES) >$@ || (rm -f $@; exit 1)
|
||||
rm -f symlist.p
|
||||
CLEANFILES += symlist.c
|
||||
BUILT_SOURCES += symlist.c
|
||||
|
||||
if COND_HAVE_ASM_USCORE
|
||||
ASM_PREFIX=_
|
||||
else
|
||||
ASM_PREFIX=
|
||||
endif
|
||||
|
||||
noinst_DATA += kernel_syms.lst
|
||||
|
||||
kernel_syms.lst: $(KERNEL_HEADER_FILES) $(top_builddir)/config.h
|
||||
$(TARGET_CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS_KERNEL) $(CPPFLAGS) $(CFLAGS) -DGRUB_SYMBOL_GENERATOR=1 $^ >kernel_syms.input
|
||||
cat kernel_syms.input | grep -v '^#' | sed -n \
|
||||
-e '/EXPORT_FUNC *([a-zA-Z0-9_]*)/{s/.*EXPORT_FUNC *(\([a-zA-Z0-9_]*\)).*/defined kernel '"$(ASM_PREFIX)"'\1/;p;}' \
|
||||
-e '/EXPORT_VAR *([a-zA-Z0-9_]*)/{s/.*EXPORT_VAR *(\([a-zA-Z0-9_]*\)).*/defined kernel '"$(ASM_PREFIX)"'\1/;p;}' \
|
||||
| sort -u >$@
|
||||
rm -f kernel_syms.input
|
||||
CLEANFILES += kernel_syms.lst
|
||||
|
||||
if COND_emu
|
||||
kern/emu/grub_emu-main.$(OBJEXT):grub_emu_init.h
|
||||
grub_emu-grub_emu_init.$(OBJEXT):grub_emu_init.h
|
||||
kern/emu/grub_emu_dyn-main.$(OBJEXT):grub_emu_init.h
|
||||
grub_emu_dyn-grub_emu_init.$(OBJEXT):grub_emu_init.h
|
||||
|
||||
grub_emu_init.h: genemuinitheader.sh $(MODULE_FILES)
|
||||
rm -f $@; echo $(MODULE_FILES) | sh $(srcdir)/genemuinitheader.sh $(TARGET_NM) > $@
|
||||
CLEANFILES += grub_emu_init.h
|
||||
|
||||
grub_emu_init.c: grub_emu_init.h genemuinit.sh $(MODULE_FILES)
|
||||
rm -f $@; echo $(MODULE_FILES) | sh $(srcdir)/genemuinit.sh $(TARGET_NM) > $@
|
||||
CLEANFILES += grub_emu_init.c
|
||||
endif
|
||||
|
||||
# List files
|
||||
|
||||
fs.lst: $(MARKER_FILES)
|
||||
(for pp in $^; do \
|
||||
b=`basename $$pp .marker`; \
|
||||
if grep 'FS_LIST_MARKER' $$pp >/dev/null 2>&1; then \
|
||||
echo $$b; \
|
||||
fi; \
|
||||
done) | sort -u > $@
|
||||
platform_DATA += fs.lst
|
||||
CLEANFILES += fs.lst
|
||||
|
||||
command.lst: $(MARKER_FILES)
|
||||
(for pp in $^; do \
|
||||
b=`basename $$pp .marker`; \
|
||||
sed -n \
|
||||
-e "/EXTCOMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/*\1: $$b/;p;}" \
|
||||
-e "/P1COMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/*\1: $$b/;p;}" \
|
||||
-e "/COMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/\1: $$b/;p;}" $$pp; \
|
||||
done) | sort -u > $@
|
||||
platform_DATA += command.lst
|
||||
CLEANFILES += command.lst
|
||||
|
||||
partmap.lst: $(MARKER_FILES)
|
||||
(for pp in $^; do \
|
||||
b=`basename $$pp .marker`; \
|
||||
if grep 'PARTMAP_LIST_MARKER' $$pp >/dev/null 2>&1; then \
|
||||
echo $$b; \
|
||||
fi; \
|
||||
done) | sort -u > $@
|
||||
platform_DATA += partmap.lst
|
||||
CLEANFILES += partmap.lst
|
||||
|
||||
terminal.lst: $(MARKER_FILES)
|
||||
(for pp in $^; do \
|
||||
b=`basename $$pp .marker`; \
|
||||
sed -n \
|
||||
-e "/INPUT_TERMINAL_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/i\1: $$b/;p;}" \
|
||||
-e "/OUTPUT_TERMINAL_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/o\1: $$b/;p;}" $$pp; \
|
||||
done) | sort -u > $@
|
||||
platform_DATA += terminal.lst
|
||||
CLEANFILES += terminal.lst
|
||||
|
||||
fdt.lst: $(MARKER_FILES)
|
||||
(for pp in $^; do \
|
||||
b=`basename $$pp .marker`; \
|
||||
sed -n \
|
||||
-e "/FDT_DRIVER_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/i\1: $$b/;p;}" \
|
||||
-e "/FDT_DRIVER_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/o\1: $$b/;p;}" $$pp; \
|
||||
done) | sort -u > $@
|
||||
platform_DATA += fdt.lst
|
||||
CLEANFILES += fdt.lst
|
||||
|
||||
parttool.lst: $(MARKER_FILES)
|
||||
(for pp in $^; do \
|
||||
b=`basename $$pp .marker`; \
|
||||
sed -n \
|
||||
-e "/PARTTOOL_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/\1: $$b/;p;}" $$pp; \
|
||||
done) | sort -u > $@
|
||||
platform_DATA += parttool.lst
|
||||
CLEANFILES += parttool.lst
|
||||
|
||||
video.lst: $(MARKER_FILES)
|
||||
(for pp in $^; do \
|
||||
b=`basename $$pp .marker`; \
|
||||
if grep 'VIDEO_LIST_MARKER' $$pp >/dev/null 2>&1; then \
|
||||
echo $$b; \
|
||||
fi; \
|
||||
done) | sort -u > $@
|
||||
platform_DATA += video.lst
|
||||
CLEANFILES += video.lst
|
||||
|
||||
# but, crypto.lst is simply copied
|
||||
crypto.lst: $(srcdir)/lib/libgcrypt-grub/cipher/crypto.lst
|
||||
cp $^ $@
|
||||
platform_DATA += crypto.lst
|
||||
CLEANFILES += crypto.lst
|
||||
|
||||
syminfo.lst: gensyminfo.sh kernel_syms.lst $(MODULE_FILES)
|
||||
cat kernel_syms.lst > $@.new
|
||||
for m in $(MODULE_FILES); do \
|
||||
sh $< $$m >> $@.new || exit 1; \
|
||||
done
|
||||
mv $@.new $@
|
||||
|
||||
# generate global module dependencies list
|
||||
moddep.lst: syminfo.lst genmoddep.awk video.lst
|
||||
cat $< | sort | $(AWK) -f $(srcdir)/genmoddep.awk > $@ || (rm -f $@; exit 1)
|
||||
platform_DATA += moddep.lst
|
||||
CLEANFILES += config.log syminfo.lst moddep.lst
|
||||
|
||||
$(MOD_FILES): %.mod : genmod.sh moddep.lst %.module$(EXEEXT) build-grub-module-verifier$(BUILD_EXEEXT)
|
||||
TARGET_OBJ2ELF=@TARGET_OBJ2ELF@ sh $^ $@
|
||||
platform_DATA += $(MOD_FILES)
|
||||
platform_DATA += modinfo.sh
|
||||
CLEANFILES += $(MOD_FILES)
|
||||
|
||||
if COND_ENABLE_EFIEMU
|
||||
efiemu32.o: efiemu/runtime/efiemu.c $(TARGET_OBJ2ELF)
|
||||
-rm -f $@
|
||||
-rm -f $@.bin
|
||||
$(TARGET_CC) $(DEFS) $(INCLUDES) $(CPPFLAGS_EFIEMU) $(CPPFLAGS_DEFAULT) -m32 -Wall -Werror -nostdlib -static -O2 -c -o $@.bin $<
|
||||
if test "x$(TARGET_APPLE_LINKER)" = x1; then \
|
||||
$(TARGET_OBJCONV) -felf32 -nu -nd $@.bin $@ || exit 1; \
|
||||
rm -f $@.bin ; \
|
||||
elif test ! -z "$(TARGET_OBJ2ELF)"; then \
|
||||
$(TARGET_OBJ2ELF) $@.bin || (rm -f $@.bin; exit 1); \
|
||||
mv $@.bin $@ ; \
|
||||
else \
|
||||
mv $@.bin $@ ; \
|
||||
fi
|
||||
|
||||
# Link format -arch,x86_64 means Apple linker
|
||||
efiemu64_c.o: efiemu/runtime/efiemu.c
|
||||
$(TARGET_CC) $(DEFS) $(INCLUDES) $(CPPFLAGS_EFIEMU) $(CPPFLAGS_DEFAULT) -m64 -nostdlib -Wall -Werror -O2 -mcmodel=large -mno-red-zone -c -o $@ $<
|
||||
|
||||
efiemu64_s.o: efiemu/runtime/efiemu.S
|
||||
$(TARGET_CC) $(DEFS) $(INCLUDES) $(CPPFLAGS_EFIEMU) $(CPPFLAGS_DEFAULT) -m64 -Wall -Werror -nostdlib -O2 -mcmodel=large -mno-red-zone -c -o $@ $<
|
||||
|
||||
efiemu64.o: efiemu64_c.o efiemu64_s.o $(TARGET_OBJ2ELEF)
|
||||
-rm -f $@
|
||||
-rm -f $@.bin
|
||||
$(TARGET_CC) -m64 $(EFIEMU64_LINK_FORMAT) -nostdlib -static -Wl,-r -o $@.bin $^
|
||||
if test "x$(EFIEMU64_LINK_FORMAT)" = x-arch,x86_64; then \
|
||||
$(TARGET_OBJCONV) -felf64 -nu -nd $@.bin $@ || exit 1; \
|
||||
rm -f $@.bin; \
|
||||
else \
|
||||
mv $@.bin $@ ; \
|
||||
fi
|
||||
|
||||
platform_DATA += efiemu32.o efiemu64.o
|
||||
CLEANFILES += efiemu32.o efiemu64.o efiemu64_c.o efiemu64_s.o
|
||||
endif
|
||||
|
||||
windowsdir=$(top_builddir)/$(PACKAGE)-$(VERSION)-for-windows
|
||||
windowsdir: $(PROGRAMS) $(starfield_DATA) $(platform_DATA)
|
||||
test -d $(windowsdir)/$(target_cpu)-$(platform) || mkdir $(windowsdir)/$(target_cpu)-$(platform)
|
||||
for x in $(platform_DATA); do \
|
||||
cp -fp $$x $(windowsdir)/$(target_cpu)-$(platform)/$$x; \
|
||||
done
|
@ -100,6 +100,10 @@ kernel = {
|
||||
emu_cppflags = '$(CPPFLAGS_GNULIB)';
|
||||
arm_uboot_ldflags = '-Wl,-r,-d';
|
||||
arm_uboot_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version';
|
||||
|
||||
mips64_efi_ldflags = '-Wl,-r,-d';
|
||||
mips64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version -R .eh_frame -R .MIPS.abiflags';
|
||||
|
||||
arm_coreboot_ldflags = '-Wl,-r,-d';
|
||||
arm_coreboot_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version';
|
||||
|
||||
@ -114,6 +118,7 @@ kernel = {
|
||||
i386_coreboot_startup = kern/i386/coreboot/startup.S;
|
||||
i386_multiboot_startup = kern/i386/coreboot/startup.S;
|
||||
mips_startup = kern/mips/startup.S;
|
||||
mips64_efi_startup = kern/mips64/efi/startup.S;
|
||||
sparc64_ieee1275_startup = kern/sparc64/ieee1275/crt0.S;
|
||||
powerpc_ieee1275_startup = kern/powerpc/ieee1275/startup.S;
|
||||
arm_uboot_startup = kern/arm/startup.S;
|
||||
@ -310,6 +315,15 @@ kernel = {
|
||||
extra_dist = video/sis315_init.c;
|
||||
mips_loongson = commands/keylayouts.c;
|
||||
|
||||
mips64 = kern/mips64/init.c;
|
||||
mips64 = kern/mips64/dl.c;
|
||||
mips64 = kern/mips64/cache.S;
|
||||
mips64 = kern/generic/rtc_get_time_ms.c;
|
||||
mips64_efi = kern/mips64/efi/init.c;
|
||||
mips64_efi = kern/mips64/efi/loongson.c;
|
||||
mips64_efi = lib/mips64/efi/loongson.c;
|
||||
mips64_efi = lib/mips64/efi/loongson_asm.S;
|
||||
|
||||
powerpc_ieee1275 = kern/powerpc/cache.S;
|
||||
powerpc_ieee1275 = kern/powerpc/dl.c;
|
||||
powerpc_ieee1275 = kern/powerpc/compiler-rt.S;
|
||||
@ -809,6 +823,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;
|
||||
@ -818,6 +842,7 @@ module = {
|
||||
enable = sparc64_ieee1275;
|
||||
enable = powerpc_ieee1275;
|
||||
enable = mips_arc;
|
||||
enable = mips64_efi;
|
||||
enable = ia64_efi;
|
||||
enable = arm_efi;
|
||||
enable = arm64_efi;
|
||||
@ -986,6 +1011,7 @@ module = {
|
||||
module = {
|
||||
name = loadenv;
|
||||
common = commands/loadenv.c;
|
||||
common = commands/loadenv.h;
|
||||
common = lib/envblk.c;
|
||||
};
|
||||
|
||||
@ -1577,12 +1603,22 @@ module = {
|
||||
module = {
|
||||
name = ventoy;
|
||||
common = ventoy/ventoy.c;
|
||||
common = ventoy/ventoy_cmd.c;
|
||||
common = ventoy/ventoy_linux.c;
|
||||
common = ventoy/ventoy_unix.c;
|
||||
common = ventoy/ventoy_windows.c;
|
||||
common = ventoy/ventoy_vhd.c;
|
||||
common = ventoy/ventoy_plugin.c;
|
||||
common = ventoy/ventoy_json.c;
|
||||
common = ventoy/lzx.c;
|
||||
common = ventoy/xpress.c;
|
||||
common = ventoy/huffman.c;
|
||||
common = ventoy/miniz.c;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = setkey;
|
||||
common = term/setkey.c;
|
||||
};
|
||||
|
||||
module = {
|
||||
@ -1647,6 +1683,8 @@ module = {
|
||||
efi = lib/efi/relocator.c;
|
||||
mips = lib/mips/relocator_asm.S;
|
||||
mips = lib/mips/relocator.c;
|
||||
mips64 = lib/mips64/relocator_asm.S;
|
||||
mips64 = lib/mips64/relocator.c;
|
||||
powerpc = lib/powerpc/relocator_asm.S;
|
||||
powerpc = lib/powerpc/relocator.c;
|
||||
xen = lib/xen/relocator.c;
|
||||
@ -1659,6 +1697,7 @@ module = {
|
||||
extra_dist = kern/powerpc/cache_flush.S;
|
||||
|
||||
enable = mips;
|
||||
enable = mips64;
|
||||
enable = powerpc;
|
||||
enable = x86;
|
||||
enable = i386_xen_pvh;
|
||||
@ -1789,6 +1828,7 @@ module = {
|
||||
i386_pc = lib/i386/pc/vesa_modes_table.c;
|
||||
i386_xen_pvh = lib/i386/pc/vesa_modes_table.c;
|
||||
mips = loader/mips/linux.c;
|
||||
mips64 = loader/mips64/linux.c;
|
||||
powerpc_ieee1275 = loader/powerpc/ieee1275/linux.c;
|
||||
sparc64_ieee1275 = loader/sparc64/ieee1275/linux.c;
|
||||
ia64_efi = loader/ia64/efi/linux.c;
|
||||
@ -1895,6 +1935,7 @@ module = {
|
||||
enable = riscv32_efi;
|
||||
enable = riscv64_efi;
|
||||
enable = mips;
|
||||
enable = mips64_efi;
|
||||
};
|
||||
|
||||
module = {
|
||||
|
@ -479,7 +479,7 @@ LOCAL(stop):
|
||||
jmp LOCAL(stop)
|
||||
|
||||
ventoy_uuid: .ascii "XXXXXXXXXXXXXXXX"
|
||||
notification_string: .asciz "GR"
|
||||
notification_string: .asciz "VT"
|
||||
geometry_error_string: .asciz "Ge"
|
||||
hd_probe_error_string: .asciz "HD"
|
||||
read_error_string: .asciz "Rd"
|
||||
|
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
343
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/hashsum.c
Normal file
343
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/hashsum.c
Normal file
@ -0,0 +1,343 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include <grub/dl.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/crypto.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static const struct grub_arg_option options[] = {
|
||||
{"hash", 'h', 0, N_("Specify hash to use."), N_("HASH"), ARG_TYPE_STRING},
|
||||
{"check", 'c', 0, N_("Check hashes of files with hash list FILE."),
|
||||
N_("FILE"), ARG_TYPE_STRING},
|
||||
{"prefix", 'p', 0, N_("Base directory for hash list."), N_("DIR"),
|
||||
ARG_TYPE_STRING},
|
||||
{"keep-going", 'k', 0, N_("Don't stop after first error."), 0, 0},
|
||||
{"uncompress", 'u', 0, N_("Uncompress file before checksumming."), 0, 0},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static struct { const char *name; const char *hashname; } aliases[] =
|
||||
{
|
||||
{"sha256sum", "sha256"},
|
||||
{"sha512sum", "sha512"},
|
||||
{"sha1sum", "sha1"},
|
||||
{"md5sum", "md5"},
|
||||
{"crc", "crc32"},
|
||||
};
|
||||
|
||||
static inline int
|
||||
hextoval (char c)
|
||||
{
|
||||
if (c >= '0' && c <= '9')
|
||||
return c - '0';
|
||||
if (c >= 'a' && c <= 'f')
|
||||
return c - 'a' + 10;
|
||||
if (c >= 'A' && c <= 'F')
|
||||
return c - 'A' + 10;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
hash_file (grub_file_t file, const gcry_md_spec_t *hash, void *result)
|
||||
{
|
||||
int progress = 0;
|
||||
grub_uint64_t ro = 0;
|
||||
grub_uint64_t div = 0;
|
||||
grub_uint64_t total = 0;
|
||||
void *context;
|
||||
grub_uint8_t *readbuf;
|
||||
#define BUF_SIZE 1024 * 1024
|
||||
readbuf = grub_malloc (BUF_SIZE);
|
||||
if (!readbuf)
|
||||
return grub_errno;
|
||||
context = grub_zalloc (hash->contextsize);
|
||||
if (!readbuf || !context)
|
||||
goto fail;
|
||||
|
||||
if (file->size > 16 * 1024 * 1024)
|
||||
progress = 1;
|
||||
|
||||
hash->init (context);
|
||||
while (1)
|
||||
{
|
||||
grub_ssize_t r;
|
||||
r = grub_file_read (file, readbuf, BUF_SIZE);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
if (r == 0)
|
||||
break;
|
||||
hash->write (context, readbuf, r);
|
||||
if (progress)
|
||||
{
|
||||
total += r;
|
||||
div = grub_divmod64(total * 100, (grub_uint64_t)file->size, &ro);
|
||||
grub_printf("\rCalculating %d%% ", (int)div);
|
||||
grub_refresh();
|
||||
}
|
||||
}
|
||||
hash->final (context);
|
||||
grub_memcpy (result, hash->read (context), hash->mdlen);
|
||||
|
||||
grub_free (readbuf);
|
||||
grub_free (context);
|
||||
if (progress)
|
||||
{
|
||||
grub_printf("\rCalculating 100%% \n\r\n");
|
||||
grub_refresh();
|
||||
}
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
fail:
|
||||
grub_free (readbuf);
|
||||
grub_free (context);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
check_list (const gcry_md_spec_t *hash, const char *hashfilename,
|
||||
const char *prefix, int keep, int uncompress)
|
||||
{
|
||||
grub_file_t hashlist, file;
|
||||
char *buf = NULL;
|
||||
grub_uint8_t expected[GRUB_CRYPTO_MAX_MDLEN];
|
||||
grub_uint8_t actual[GRUB_CRYPTO_MAX_MDLEN];
|
||||
grub_err_t err;
|
||||
unsigned i;
|
||||
unsigned unread = 0, mismatch = 0;
|
||||
|
||||
if (hash->mdlen > GRUB_CRYPTO_MAX_MDLEN)
|
||||
return grub_error (GRUB_ERR_BUG, "mdlen is too long");
|
||||
|
||||
hashlist = grub_file_open (hashfilename, GRUB_FILE_TYPE_HASHLIST);
|
||||
if (!hashlist)
|
||||
return grub_errno;
|
||||
|
||||
while (grub_free (buf), (buf = grub_file_getline (hashlist)))
|
||||
{
|
||||
const char *p = buf;
|
||||
while (grub_isspace (p[0]))
|
||||
p++;
|
||||
for (i = 0; i < hash->mdlen; i++)
|
||||
{
|
||||
int high, low;
|
||||
high = hextoval (*p++);
|
||||
low = hextoval (*p++);
|
||||
if (high < 0 || low < 0)
|
||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "invalid hash list");
|
||||
expected[i] = (high << 4) | low;
|
||||
}
|
||||
if ((p[0] != ' ' && p[0] != '\t') || (p[1] != ' ' && p[1] != '\t'))
|
||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "invalid hash list");
|
||||
p += 2;
|
||||
if (prefix)
|
||||
{
|
||||
char *filename;
|
||||
|
||||
filename = grub_xasprintf ("%s/%s", prefix, p);
|
||||
if (!filename)
|
||||
return grub_errno;
|
||||
file = grub_file_open (filename, GRUB_FILE_TYPE_TO_HASH
|
||||
| (!uncompress ? GRUB_FILE_TYPE_NO_DECOMPRESS
|
||||
: GRUB_FILE_TYPE_NONE));
|
||||
grub_free (filename);
|
||||
}
|
||||
else
|
||||
file = grub_file_open (p, GRUB_FILE_TYPE_TO_HASH
|
||||
| (!uncompress ? GRUB_FILE_TYPE_NO_DECOMPRESS
|
||||
: GRUB_FILE_TYPE_NONE));
|
||||
if (!file)
|
||||
{
|
||||
grub_file_close (hashlist);
|
||||
grub_free (buf);
|
||||
return grub_errno;
|
||||
}
|
||||
err = hash_file (file, hash, actual);
|
||||
grub_file_close (file);
|
||||
if (err)
|
||||
{
|
||||
grub_printf_ (N_("%s: READ ERROR\n"), p);
|
||||
if (!keep)
|
||||
{
|
||||
grub_file_close (hashlist);
|
||||
grub_free (buf);
|
||||
return err;
|
||||
}
|
||||
grub_print_error ();
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
unread++;
|
||||
continue;
|
||||
}
|
||||
if (grub_crypto_memcmp (expected, actual, hash->mdlen) != 0)
|
||||
{
|
||||
grub_printf_ (N_("%s: HASH MISMATCH\n"), p);
|
||||
if (!keep)
|
||||
{
|
||||
grub_file_close (hashlist);
|
||||
grub_free (buf);
|
||||
return grub_error (GRUB_ERR_TEST_FAILURE,
|
||||
"hash of '%s' mismatches", p);
|
||||
}
|
||||
mismatch++;
|
||||
continue;
|
||||
}
|
||||
grub_printf_ (N_("%s: OK\n"), p);
|
||||
}
|
||||
if (mismatch || unread)
|
||||
return grub_error (GRUB_ERR_TEST_FAILURE,
|
||||
"%d files couldn't be read and hash "
|
||||
"of %d files mismatches", unread, mismatch);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_hashsum (struct grub_extcmd_context *ctxt,
|
||||
int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
const char *hashname = NULL;
|
||||
const char *prefix = NULL;
|
||||
const gcry_md_spec_t *hash;
|
||||
unsigned i;
|
||||
int keep = state[3].set;
|
||||
int uncompress = state[4].set;
|
||||
unsigned unread = 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE (aliases); i++)
|
||||
if (grub_strcmp (ctxt->extcmd->cmd->name, aliases[i].name) == 0)
|
||||
hashname = aliases[i].hashname;
|
||||
if (state[0].set)
|
||||
hashname = state[0].arg;
|
||||
|
||||
if (!hashname)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no hash specified");
|
||||
|
||||
hash = grub_crypto_lookup_md_by_name (hashname);
|
||||
if (!hash)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown hash");
|
||||
|
||||
if (hash->mdlen > GRUB_CRYPTO_MAX_MDLEN)
|
||||
return grub_error (GRUB_ERR_BUG, "mdlen is too long");
|
||||
|
||||
if (state[2].set)
|
||||
prefix = state[2].arg;
|
||||
|
||||
if (state[1].set)
|
||||
{
|
||||
if (argc != 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"--check is incompatible with file list");
|
||||
return check_list (hash, state[1].arg, prefix, keep, uncompress);
|
||||
}
|
||||
|
||||
for (i = 0; i < (unsigned) argc; i++)
|
||||
{
|
||||
GRUB_PROPERLY_ALIGNED_ARRAY (result, GRUB_CRYPTO_MAX_MDLEN);
|
||||
grub_file_t file;
|
||||
grub_err_t err;
|
||||
unsigned j;
|
||||
file = grub_file_open (args[i], GRUB_FILE_TYPE_TO_HASH
|
||||
| (!uncompress ? GRUB_FILE_TYPE_NO_DECOMPRESS
|
||||
: GRUB_FILE_TYPE_NONE));
|
||||
if (!file)
|
||||
{
|
||||
if (!keep)
|
||||
return grub_errno;
|
||||
grub_print_error ();
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
unread++;
|
||||
continue;
|
||||
}
|
||||
err = hash_file (file, hash, result);
|
||||
grub_file_close (file);
|
||||
if (err)
|
||||
{
|
||||
if (!keep)
|
||||
return err;
|
||||
grub_print_error ();
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
unread++;
|
||||
continue;
|
||||
}
|
||||
for (j = 0; j < hash->mdlen; j++)
|
||||
grub_printf ("%02x", ((grub_uint8_t *) result)[j]);
|
||||
grub_printf (" %s\n", args[i]);
|
||||
}
|
||||
|
||||
if (unread)
|
||||
return grub_error (GRUB_ERR_TEST_FAILURE, "%d files couldn't be read",
|
||||
unread);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd, cmd_md5, cmd_sha1, cmd_sha256, cmd_sha512, cmd_crc;
|
||||
|
||||
GRUB_MOD_INIT(hashsum)
|
||||
{
|
||||
cmd = grub_register_extcmd ("hashsum", grub_cmd_hashsum, 0,
|
||||
N_("-h HASH [-c FILE [-p PREFIX]] "
|
||||
"[FILE1 [FILE2 ...]]"),
|
||||
/* TRANSLATORS: "hash checksum" is just to
|
||||
be a bit more precise, you can treat it as
|
||||
just "hash". */
|
||||
N_("Compute or check hash checksum."),
|
||||
options);
|
||||
cmd_md5 = grub_register_extcmd ("md5sum", grub_cmd_hashsum, 0,
|
||||
N_("[-c FILE [-p PREFIX]] "
|
||||
"[FILE1 [FILE2 ...]]"),
|
||||
N_("Compute or check hash checksum."),
|
||||
options);
|
||||
cmd_sha1 = grub_register_extcmd ("sha1sum", grub_cmd_hashsum, 0,
|
||||
N_("[-c FILE [-p PREFIX]] "
|
||||
"[FILE1 [FILE2 ...]]"),
|
||||
N_("Compute or check hash checksum."),
|
||||
options);
|
||||
cmd_sha256 = grub_register_extcmd ("sha256sum", grub_cmd_hashsum, 0,
|
||||
N_("[-c FILE [-p PREFIX]] "
|
||||
"[FILE1 [FILE2 ...]]"),
|
||||
N_("Compute or check hash checksum."),
|
||||
options);
|
||||
cmd_sha512 = grub_register_extcmd ("sha512sum", grub_cmd_hashsum, 0,
|
||||
N_("[-c FILE [-p PREFIX]] "
|
||||
"[FILE1 [FILE2 ...]]"),
|
||||
N_("Compute or check hash checksum."),
|
||||
options);
|
||||
|
||||
cmd_crc = grub_register_extcmd ("crc", grub_cmd_hashsum, 0,
|
||||
N_("[-c FILE [-p PREFIX]] "
|
||||
"[FILE1 [FILE2 ...]]"),
|
||||
N_("Compute or check hash checksum."),
|
||||
options);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(hashsum)
|
||||
{
|
||||
grub_unregister_extcmd (cmd);
|
||||
grub_unregister_extcmd (cmd_md5);
|
||||
grub_unregister_extcmd (cmd_sha1);
|
||||
grub_unregister_extcmd (cmd_sha256);
|
||||
grub_unregister_extcmd (cmd_sha512);
|
||||
grub_unregister_extcmd (cmd_crc);
|
||||
}
|
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);
|
||||
}
|
353
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/search.c
Normal file
353
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/search.c
Normal file
@ -0,0 +1,353 @@
|
||||
/* search.c - search devices based on a file or a filesystem label */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2005,2007,2008,2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/types.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/device.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/search.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/partition.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static int g_no_vtoyefi_part = 0;
|
||||
static char g_vtoyefi_dosname[64];
|
||||
static char g_vtoyefi_gptname[64];
|
||||
|
||||
struct cache_entry
|
||||
{
|
||||
struct cache_entry *next;
|
||||
char *key;
|
||||
char *value;
|
||||
};
|
||||
|
||||
static struct cache_entry *cache;
|
||||
|
||||
/* Context for FUNC_NAME. */
|
||||
struct search_ctx
|
||||
{
|
||||
const char *key;
|
||||
const char *var;
|
||||
int no_floppy;
|
||||
char **hints;
|
||||
unsigned nhints;
|
||||
int count;
|
||||
int is_cache;
|
||||
};
|
||||
|
||||
/* Helper for FUNC_NAME. */
|
||||
static int
|
||||
iterate_device (const char *name, void *data)
|
||||
{
|
||||
struct search_ctx *ctx = data;
|
||||
int found = 0;
|
||||
|
||||
/* Skip floppy drives when requested. */
|
||||
if (ctx->no_floppy &&
|
||||
name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9')
|
||||
return 1;
|
||||
|
||||
if (g_no_vtoyefi_part && (grub_strcmp(name, g_vtoyefi_dosname) == 0 || grub_strcmp(name, g_vtoyefi_gptname) == 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DO_SEARCH_FS_UUID
|
||||
#define compare_fn grub_strcasecmp
|
||||
#else
|
||||
#define compare_fn grub_strcmp
|
||||
#endif
|
||||
|
||||
#ifdef DO_SEARCH_FILE
|
||||
{
|
||||
char *buf;
|
||||
grub_file_t file;
|
||||
|
||||
buf = grub_xasprintf ("(%s)%s", name, ctx->key);
|
||||
if (! buf)
|
||||
return 1;
|
||||
|
||||
file = grub_file_open (buf, GRUB_FILE_TYPE_FS_SEARCH
|
||||
| GRUB_FILE_TYPE_NO_DECOMPRESS);
|
||||
if (file)
|
||||
{
|
||||
found = 1;
|
||||
grub_file_close (file);
|
||||
}
|
||||
grub_free (buf);
|
||||
}
|
||||
#else
|
||||
{
|
||||
/* SEARCH_FS_UUID or SEARCH_LABEL */
|
||||
grub_device_t dev;
|
||||
grub_fs_t fs;
|
||||
char *quid;
|
||||
|
||||
dev = grub_device_open (name);
|
||||
if (dev)
|
||||
{
|
||||
fs = grub_fs_probe (dev);
|
||||
|
||||
#ifdef DO_SEARCH_FS_UUID
|
||||
#define read_fn fs_uuid
|
||||
#else
|
||||
#define read_fn fs_label
|
||||
#endif
|
||||
|
||||
if (fs && fs->read_fn)
|
||||
{
|
||||
fs->read_fn (dev, &quid);
|
||||
|
||||
if (grub_errno == GRUB_ERR_NONE && quid)
|
||||
{
|
||||
if (compare_fn (quid, ctx->key) == 0)
|
||||
found = 1;
|
||||
|
||||
grub_free (quid);
|
||||
}
|
||||
}
|
||||
|
||||
grub_device_close (dev);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!ctx->is_cache && found && ctx->count == 0)
|
||||
{
|
||||
struct cache_entry *cache_ent;
|
||||
cache_ent = grub_malloc (sizeof (*cache_ent));
|
||||
if (cache_ent)
|
||||
{
|
||||
cache_ent->key = grub_strdup (ctx->key);
|
||||
cache_ent->value = grub_strdup (name);
|
||||
if (cache_ent->value && cache_ent->key)
|
||||
{
|
||||
cache_ent->next = cache;
|
||||
cache = cache_ent;
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_free (cache_ent->value);
|
||||
grub_free (cache_ent->key);
|
||||
grub_free (cache_ent);
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
}
|
||||
else
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
ctx->count++;
|
||||
if (ctx->var)
|
||||
grub_env_set (ctx->var, name);
|
||||
else
|
||||
grub_printf (" %s", name);
|
||||
}
|
||||
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
return (found && ctx->var);
|
||||
}
|
||||
|
||||
/* Helper for FUNC_NAME. */
|
||||
static int
|
||||
part_hook (grub_disk_t disk, const grub_partition_t partition, void *data)
|
||||
{
|
||||
struct search_ctx *ctx = data;
|
||||
char *partition_name, *devname;
|
||||
int ret;
|
||||
|
||||
partition_name = grub_partition_get_name (partition);
|
||||
if (! partition_name)
|
||||
return 1;
|
||||
|
||||
devname = grub_xasprintf ("%s,%s", disk->name, partition_name);
|
||||
grub_free (partition_name);
|
||||
if (!devname)
|
||||
return 1;
|
||||
ret = iterate_device (devname, ctx);
|
||||
grub_free (devname);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Helper for FUNC_NAME. */
|
||||
static void
|
||||
try (struct search_ctx *ctx)
|
||||
{
|
||||
unsigned i;
|
||||
struct cache_entry **prev;
|
||||
struct cache_entry *cache_ent;
|
||||
|
||||
for (prev = &cache, cache_ent = *prev; cache_ent;
|
||||
prev = &cache_ent->next, cache_ent = *prev)
|
||||
if (compare_fn (cache_ent->key, ctx->key) == 0)
|
||||
break;
|
||||
if (cache_ent)
|
||||
{
|
||||
ctx->is_cache = 1;
|
||||
if (iterate_device (cache_ent->value, ctx))
|
||||
{
|
||||
ctx->is_cache = 0;
|
||||
return;
|
||||
}
|
||||
ctx->is_cache = 0;
|
||||
/* Cache entry was outdated. Remove it. */
|
||||
if (!ctx->count)
|
||||
{
|
||||
*prev = cache_ent->next;
|
||||
grub_free (cache_ent->key);
|
||||
grub_free (cache_ent->value);
|
||||
grub_free (cache_ent);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ctx->nhints; i++)
|
||||
{
|
||||
char *end;
|
||||
if (!ctx->hints[i][0])
|
||||
continue;
|
||||
end = ctx->hints[i] + grub_strlen (ctx->hints[i]) - 1;
|
||||
if (*end == ',')
|
||||
*end = 0;
|
||||
if (iterate_device (ctx->hints[i], ctx))
|
||||
{
|
||||
if (!*end)
|
||||
*end = ',';
|
||||
return;
|
||||
}
|
||||
if (!*end)
|
||||
{
|
||||
grub_device_t dev;
|
||||
int ret;
|
||||
dev = grub_device_open (ctx->hints[i]);
|
||||
if (!dev)
|
||||
{
|
||||
if (!*end)
|
||||
*end = ',';
|
||||
continue;
|
||||
}
|
||||
if (!dev->disk)
|
||||
{
|
||||
grub_device_close (dev);
|
||||
if (!*end)
|
||||
*end = ',';
|
||||
continue;
|
||||
}
|
||||
ret = grub_partition_iterate (dev->disk, part_hook, ctx);
|
||||
if (!*end)
|
||||
*end = ',';
|
||||
grub_device_close (dev);
|
||||
if (ret)
|
||||
return;
|
||||
}
|
||||
}
|
||||
grub_device_iterate (iterate_device, ctx);
|
||||
}
|
||||
|
||||
void
|
||||
FUNC_NAME (const char *key, const char *var, int no_floppy,
|
||||
char **hints, unsigned nhints)
|
||||
{
|
||||
struct search_ctx ctx = {
|
||||
.key = key,
|
||||
.var = var,
|
||||
.no_floppy = no_floppy,
|
||||
.hints = hints,
|
||||
.nhints = nhints,
|
||||
.count = 0,
|
||||
.is_cache = 0
|
||||
};
|
||||
grub_fs_autoload_hook_t saved_autoload;
|
||||
|
||||
g_no_vtoyefi_part = 0;
|
||||
if (grub_env_get("VTOY_SEARCH_NO_VTOYEFI"))
|
||||
{
|
||||
grub_snprintf(g_vtoyefi_dosname, sizeof(g_vtoyefi_dosname), "%s,msdos2", grub_env_get("vtoydev"));
|
||||
grub_snprintf(g_vtoyefi_gptname, sizeof(g_vtoyefi_gptname), "%s,gpt2", grub_env_get("vtoydev"));
|
||||
g_no_vtoyefi_part = 1;
|
||||
}
|
||||
|
||||
/* First try without autoloading if we're setting variable. */
|
||||
if (var)
|
||||
{
|
||||
saved_autoload = grub_fs_autoload_hook;
|
||||
grub_fs_autoload_hook = 0;
|
||||
try (&ctx);
|
||||
|
||||
/* Restore autoload hook. */
|
||||
grub_fs_autoload_hook = saved_autoload;
|
||||
|
||||
/* Retry with autoload if nothing found. */
|
||||
if (grub_errno == GRUB_ERR_NONE && ctx.count == 0)
|
||||
try (&ctx);
|
||||
}
|
||||
else
|
||||
try (&ctx);
|
||||
|
||||
if (grub_errno == GRUB_ERR_NONE && ctx.count == 0)
|
||||
grub_error (GRUB_ERR_FILE_NOT_FOUND, "no such device: %s", key);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_do_search (grub_command_t cmd __attribute__ ((unused)), int argc,
|
||||
char **args)
|
||||
{
|
||||
if (argc == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
|
||||
|
||||
FUNC_NAME (args[0], argc == 1 ? 0 : args[1], 0, (args + 2),
|
||||
argc > 2 ? argc - 2 : 0);
|
||||
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
#ifdef DO_SEARCH_FILE
|
||||
GRUB_MOD_INIT(search_fs_file)
|
||||
#elif defined (DO_SEARCH_FS_UUID)
|
||||
GRUB_MOD_INIT(search_fs_uuid)
|
||||
#else
|
||||
GRUB_MOD_INIT(search_label)
|
||||
#endif
|
||||
{
|
||||
cmd =
|
||||
grub_register_command (COMMAND_NAME, grub_cmd_do_search,
|
||||
N_("NAME [VARIABLE] [HINTS]"),
|
||||
HELP_MESSAGE);
|
||||
}
|
||||
|
||||
#ifdef DO_SEARCH_FILE
|
||||
GRUB_MOD_FINI(search_fs_file)
|
||||
#elif defined (DO_SEARCH_FS_UUID)
|
||||
GRUB_MOD_FINI(search_fs_uuid)
|
||||
#else
|
||||
GRUB_MOD_FINI(search_label)
|
||||
#endif
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
257
GRUB2/MOD_SRC/grub-2.04/grub-core/disk/loopback.c
Normal file
257
GRUB2/MOD_SRC/grub-2.04/grub-core/disk/loopback.c
Normal file
@ -0,0 +1,257 @@
|
||||
/* loopback.c - command to add loopback devices. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2005,2006,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/>.
|
||||
*/
|
||||
|
||||
#include <grub/dl.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
struct grub_loopback
|
||||
{
|
||||
char *devname;
|
||||
grub_file_t file;
|
||||
struct grub_loopback *next;
|
||||
unsigned long id;
|
||||
grub_off_t skip;
|
||||
};
|
||||
|
||||
static struct grub_loopback *loopback_list;
|
||||
static unsigned long last_id = 0;
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
/* TRANSLATORS: The disk is simply removed from the list of available ones,
|
||||
not wiped, avoid to scare user. */
|
||||
{"delete", 'd', 0, N_("Delete the specified loopback drive."), 0, 0},
|
||||
{"skip", 's', 0, "skip sectors of the file.", "SECTORS", ARG_TYPE_INT },
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
/* Delete the loopback device NAME. */
|
||||
static grub_err_t
|
||||
delete_loopback (const char *name)
|
||||
{
|
||||
struct grub_loopback *dev;
|
||||
struct grub_loopback **prev;
|
||||
|
||||
/* Search for the device. */
|
||||
for (dev = loopback_list, prev = &loopback_list;
|
||||
dev;
|
||||
prev = &dev->next, dev = dev->next)
|
||||
if (grub_strcmp (dev->devname, name) == 0)
|
||||
break;
|
||||
|
||||
if (! dev)
|
||||
return grub_error (GRUB_ERR_BAD_DEVICE, "device not found");
|
||||
|
||||
/* Remove the device from the list. */
|
||||
*prev = dev->next;
|
||||
|
||||
grub_free (dev->devname);
|
||||
grub_file_close (dev->file);
|
||||
grub_free (dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The command to add and remove loopback devices. */
|
||||
static grub_err_t
|
||||
grub_cmd_loopback (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
grub_file_t file;
|
||||
struct grub_loopback *newdev;
|
||||
grub_err_t ret;
|
||||
grub_off_t skip = 0;
|
||||
|
||||
if (argc < 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
|
||||
|
||||
/* Check if `-d' was used. */
|
||||
if (state[0].set)
|
||||
return delete_loopback (args[0]);
|
||||
|
||||
if (state[1].set)
|
||||
skip = (grub_off_t)grub_strtoull(state[1].arg, NULL, 10);
|
||||
|
||||
if (argc < 2)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
||||
|
||||
file = grub_file_open (args[1], GRUB_FILE_TYPE_LOOPBACK
|
||||
| GRUB_FILE_TYPE_NO_DECOMPRESS);
|
||||
if (! file)
|
||||
return grub_errno;
|
||||
|
||||
/* First try to replace the old device. */
|
||||
for (newdev = loopback_list; newdev; newdev = newdev->next)
|
||||
if (grub_strcmp (newdev->devname, args[0]) == 0)
|
||||
break;
|
||||
|
||||
if (newdev)
|
||||
{
|
||||
grub_file_close (newdev->file);
|
||||
newdev->file = file;
|
||||
newdev->skip = skip;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Unable to replace it, make a new entry. */
|
||||
newdev = grub_malloc (sizeof (struct grub_loopback));
|
||||
if (! newdev)
|
||||
goto fail;
|
||||
|
||||
newdev->devname = grub_strdup (args[0]);
|
||||
if (! newdev->devname)
|
||||
{
|
||||
grub_free (newdev);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
newdev->file = file;
|
||||
newdev->skip = skip;
|
||||
newdev->id = last_id++;
|
||||
|
||||
/* Add the new entry to the list. */
|
||||
newdev->next = loopback_list;
|
||||
loopback_list = newdev;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
ret = grub_errno;
|
||||
grub_file_close (file);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
grub_loopback_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
|
||||
grub_disk_pull_t pull)
|
||||
{
|
||||
struct grub_loopback *d;
|
||||
if (pull != GRUB_DISK_PULL_NONE)
|
||||
return 0;
|
||||
for (d = loopback_list; d; d = d->next)
|
||||
{
|
||||
if (hook (d->devname, hook_data))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_loopback_open (const char *name, grub_disk_t disk)
|
||||
{
|
||||
struct grub_loopback *dev;
|
||||
|
||||
for (dev = loopback_list; dev; dev = dev->next)
|
||||
if (grub_strcmp (dev->devname, name) == 0)
|
||||
break;
|
||||
|
||||
if (! dev)
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device");
|
||||
|
||||
/* Use the filesize for the disk size, round up to a complete sector. */
|
||||
if (dev->file->size != GRUB_FILE_SIZE_UNKNOWN)
|
||||
disk->total_sectors = ((dev->file->size + GRUB_DISK_SECTOR_SIZE - 1)
|
||||
/ GRUB_DISK_SECTOR_SIZE);
|
||||
else
|
||||
disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN;
|
||||
/* Avoid reading more than 512M. */
|
||||
disk->max_agglomerate = 1 << (29 - GRUB_DISK_SECTOR_BITS
|
||||
- GRUB_DISK_CACHE_BITS);
|
||||
|
||||
disk->id = dev->id;
|
||||
|
||||
disk->data = dev;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_loopback_read (grub_disk_t disk, grub_disk_addr_t sector,
|
||||
grub_size_t size, char *buf)
|
||||
{
|
||||
grub_file_t file = ((struct grub_loopback *) disk->data)->file;
|
||||
grub_off_t skip = ((struct grub_loopback *) disk->data)->skip;
|
||||
grub_off_t pos;
|
||||
|
||||
grub_file_seek (file, (sector + skip) << GRUB_DISK_SECTOR_BITS);
|
||||
|
||||
grub_file_read (file, buf, size << GRUB_DISK_SECTOR_BITS);
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
|
||||
/* In case there is more data read than there is available, in case
|
||||
of files that are not a multiple of GRUB_DISK_SECTOR_SIZE, fill
|
||||
the rest with zeros. */
|
||||
pos = (sector + skip + size) << GRUB_DISK_SECTOR_BITS;
|
||||
if (pos > file->size)
|
||||
{
|
||||
grub_size_t amount = pos - file->size;
|
||||
grub_memset (buf + (size << GRUB_DISK_SECTOR_BITS) - amount, 0, amount);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_loopback_write (grub_disk_t disk __attribute ((unused)),
|
||||
grub_disk_addr_t sector __attribute ((unused)),
|
||||
grub_size_t size __attribute ((unused)),
|
||||
const char *buf __attribute ((unused)))
|
||||
{
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"loopback write is not supported");
|
||||
}
|
||||
|
||||
static struct grub_disk_dev grub_loopback_dev =
|
||||
{
|
||||
.name = "loopback",
|
||||
.id = GRUB_DISK_DEVICE_LOOPBACK_ID,
|
||||
.disk_iterate = grub_loopback_iterate,
|
||||
.disk_open = grub_loopback_open,
|
||||
.disk_read = grub_loopback_read,
|
||||
.disk_write = grub_loopback_write,
|
||||
.next = 0
|
||||
};
|
||||
|
||||
static grub_extcmd_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(loopback)
|
||||
{
|
||||
cmd = grub_register_extcmd ("loopback", grub_cmd_loopback, 0,
|
||||
N_("[-d] DEVICENAME FILE."),
|
||||
/* TRANSLATORS: The file itself is not destroyed
|
||||
or transformed into drive. */
|
||||
N_("Make a virtual drive from a file."), options);
|
||||
grub_disk_dev_register (&grub_loopback_dev);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(loopback)
|
||||
{
|
||||
grub_unregister_extcmd (cmd);
|
||||
grub_disk_dev_unregister (&grub_loopback_dev);
|
||||
}
|
@ -33,6 +33,7 @@
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static int g_ventoy_no_joliet = 0;
|
||||
static int g_ventoy_cur_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;
|
||||
@ -451,6 +452,7 @@ grub_iso9660_mount (grub_disk_t disk)
|
||||
|
||||
data->disk = disk;
|
||||
|
||||
g_ventoy_cur_joliet = 0;
|
||||
block = 16;
|
||||
do
|
||||
{
|
||||
@ -484,6 +486,7 @@ grub_iso9660_mount (grub_disk_t disk)
|
||||
if (0 == g_ventoy_no_joliet) {
|
||||
copy_voldesc = 1;
|
||||
data->joliet = 1;
|
||||
g_ventoy_cur_joliet = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -735,6 +738,8 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
|
||||
{
|
||||
if ((dirent.flags & FLAG_TYPE) == FLAG_TYPE_DIR)
|
||||
ctx.type = GRUB_FSHELP_DIR;
|
||||
else if ((dirent.flags & FLAG_TYPE) == 3)
|
||||
ctx.type = GRUB_FSHELP_DIR;
|
||||
else
|
||||
ctx.type = GRUB_FSHELP_REG;
|
||||
}
|
||||
@ -1116,6 +1121,11 @@ void grub_iso9660_set_nojoliet(int nojoliet)
|
||||
g_ventoy_no_joliet = nojoliet;
|
||||
}
|
||||
|
||||
int grub_iso9660_is_joliet(void)
|
||||
{
|
||||
return g_ventoy_cur_joliet;
|
||||
}
|
||||
|
||||
grub_uint64_t grub_iso9660_get_last_read_pos(grub_file_t file)
|
||||
{
|
||||
(void)file;
|
||||
|
@ -28,6 +28,8 @@
|
||||
|
||||
extern int g_ventoy_memdisk_mode;
|
||||
extern int g_ventoy_iso_raw;
|
||||
extern int g_ventoy_grub2_mode;
|
||||
extern int g_ventoy_wimboot_mode;
|
||||
extern int g_ventoy_iso_uefi_drv;
|
||||
|
||||
static const char *align_options[] =
|
||||
@ -205,6 +207,12 @@ label_set_property (void *vself, const char *name, const char *value)
|
||||
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_GRUB2_MODE@") == 0) {
|
||||
value = g_ventoy_grub2_mode ? grub_env_get("VTOY_GRUB2_MODE_STR") : " ";
|
||||
}
|
||||
else if (grub_strcmp (value, "@VTOY_WIMBOOT_MODE@") == 0) {
|
||||
value = g_ventoy_wimboot_mode ? grub_env_get("VTOY_WIMBOOT_MODE_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") : " ";
|
||||
}
|
||||
|
839
GRUB2/MOD_SRC/grub-2.04/grub-core/gfxmenu/theme_loader.c
Normal file
839
GRUB2/MOD_SRC/grub-2.04/grub-core/gfxmenu/theme_loader.c
Normal file
@ -0,0 +1,839 @@
|
||||
/* theme_loader.c - Theme file loader for gfxmenu. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/types.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/video.h>
|
||||
#include <grub/gui_string_util.h>
|
||||
#include <grub/bitmap.h>
|
||||
#include <grub/bitmap_scale.h>
|
||||
#include <grub/gfxwidgets.h>
|
||||
#include <grub/gfxmenu_view.h>
|
||||
#include <grub/gui.h>
|
||||
#include <grub/color.h>
|
||||
#include <grub/env.h>
|
||||
|
||||
static grub_err_t
|
||||
parse_proportional_spec (const char *value, signed *abs, grub_fixed_signed_t *prop);
|
||||
|
||||
/* Construct a new box widget using ABSPATTERN to find the pixmap files for
|
||||
it, storing the new box instance at *BOXPTR.
|
||||
PATTERN should be of the form: "(hd0,0)/somewhere/style*.png".
|
||||
The '*' then gets substituted with the various pixmap names that the
|
||||
box uses. */
|
||||
static grub_err_t
|
||||
recreate_box_absolute (grub_gfxmenu_box_t *boxptr, const char *abspattern)
|
||||
{
|
||||
char *prefix;
|
||||
char *suffix;
|
||||
char *star;
|
||||
grub_gfxmenu_box_t box;
|
||||
|
||||
star = grub_strchr (abspattern, '*');
|
||||
if (! star)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"missing `*' in box pixmap pattern `%s'", abspattern);
|
||||
|
||||
/* Prefix: Get the part before the '*'. */
|
||||
prefix = grub_malloc (star - abspattern + 1);
|
||||
if (! prefix)
|
||||
return grub_errno;
|
||||
|
||||
grub_memcpy (prefix, abspattern, star - abspattern);
|
||||
prefix[star - abspattern] = '\0';
|
||||
|
||||
/* Suffix: Everything after the '*' is the suffix. */
|
||||
suffix = star + 1;
|
||||
|
||||
box = grub_gfxmenu_create_box (prefix, suffix);
|
||||
grub_free (prefix);
|
||||
if (! box)
|
||||
return grub_errno;
|
||||
|
||||
if (*boxptr)
|
||||
(*boxptr)->destroy (*boxptr);
|
||||
*boxptr = box;
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
|
||||
/* Construct a new box widget using PATTERN to find the pixmap files for it,
|
||||
storing the new widget at *BOXPTR. PATTERN should be of the form:
|
||||
"somewhere/style*.png". The '*' then gets substituted with the various
|
||||
pixmap names that the widget uses.
|
||||
|
||||
Important! The value of *BOXPTR must be initialized! It must either
|
||||
(1) Be 0 (a NULL pointer), or
|
||||
(2) Be a pointer to a valid 'grub_gfxmenu_box_t' instance.
|
||||
In this case, the previous instance is destroyed. */
|
||||
grub_err_t
|
||||
grub_gui_recreate_box (grub_gfxmenu_box_t *boxptr,
|
||||
const char *pattern, const char *theme_dir)
|
||||
{
|
||||
char *abspattern;
|
||||
|
||||
/* Check arguments. */
|
||||
if (! pattern)
|
||||
{
|
||||
/* If no pixmap pattern is given, then just create an empty box. */
|
||||
if (*boxptr)
|
||||
(*boxptr)->destroy (*boxptr);
|
||||
*boxptr = grub_gfxmenu_create_box (0, 0);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
if (! theme_dir)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"styled box missing theme directory");
|
||||
|
||||
/* Resolve to an absolute path. */
|
||||
abspattern = grub_resolve_relative_path (theme_dir, pattern);
|
||||
if (! abspattern)
|
||||
return grub_errno;
|
||||
|
||||
/* Create the box. */
|
||||
recreate_box_absolute (boxptr, abspattern);
|
||||
grub_free (abspattern);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
theme_get_unsigned_int_from_proportional (const char *value,
|
||||
unsigned absolute_value,
|
||||
unsigned int *parsed_value)
|
||||
{
|
||||
grub_err_t err;
|
||||
grub_fixed_signed_t frac;
|
||||
signed pixels;
|
||||
err = parse_proportional_spec (value, &pixels, &frac);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
int result = grub_fixed_sfs_multiply (absolute_value, frac) + pixels;
|
||||
if (result < 0)
|
||||
result = 0;
|
||||
*parsed_value = result;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
/* Set the specified property NAME on the view to the given string VALUE.
|
||||
The caller is responsible for the lifetimes of NAME and VALUE. */
|
||||
static grub_err_t
|
||||
theme_set_string (grub_gfxmenu_view_t view,
|
||||
const char *name,
|
||||
const char *value,
|
||||
const char *theme_dir,
|
||||
const char *filename,
|
||||
int line_num,
|
||||
int col_num)
|
||||
{
|
||||
if (! grub_strcmp ("title-font", name))
|
||||
view->title_font = grub_font_get (value);
|
||||
else if (! grub_strcmp ("message-font", name))
|
||||
view->message_font = grub_font_get (value);
|
||||
else if (! grub_strcmp ("terminal-font", name))
|
||||
{
|
||||
grub_free (view->terminal_font_name);
|
||||
view->terminal_font_name = grub_strdup (value);
|
||||
if (! view->terminal_font_name)
|
||||
return grub_errno;
|
||||
}
|
||||
else if (! grub_strcmp ("title-color", name))
|
||||
grub_video_parse_color (value, &view->title_color);
|
||||
else if (! grub_strcmp ("message-color", name))
|
||||
grub_video_parse_color (value, &view->message_color);
|
||||
else if (! grub_strcmp ("message-bg-color", name))
|
||||
grub_video_parse_color (value, &view->message_bg_color);
|
||||
else if (! grub_strcmp ("desktop-image", name))
|
||||
{
|
||||
struct grub_video_bitmap *raw_bitmap;
|
||||
char *path;
|
||||
path = grub_resolve_relative_path (theme_dir, value);
|
||||
if (! path)
|
||||
return grub_errno;
|
||||
if (grub_video_bitmap_load (&raw_bitmap, path) != GRUB_ERR_NONE)
|
||||
{
|
||||
grub_free (path);
|
||||
return grub_errno;
|
||||
}
|
||||
grub_free(path);
|
||||
grub_video_bitmap_destroy (view->raw_desktop_image);
|
||||
view->raw_desktop_image = raw_bitmap;
|
||||
}
|
||||
else if (! grub_strcmp ("desktop-image-scale-method", name))
|
||||
{
|
||||
if (! value || ! grub_strcmp ("stretch", value))
|
||||
view->desktop_image_scale_method =
|
||||
GRUB_VIDEO_BITMAP_SELECTION_METHOD_STRETCH;
|
||||
else if (! grub_strcmp ("crop", value))
|
||||
view->desktop_image_scale_method =
|
||||
GRUB_VIDEO_BITMAP_SELECTION_METHOD_CROP;
|
||||
else if (! grub_strcmp ("padding", value))
|
||||
view->desktop_image_scale_method =
|
||||
GRUB_VIDEO_BITMAP_SELECTION_METHOD_PADDING;
|
||||
else if (! grub_strcmp ("fitwidth", value))
|
||||
view->desktop_image_scale_method =
|
||||
GRUB_VIDEO_BITMAP_SELECTION_METHOD_FITWIDTH;
|
||||
else if (! grub_strcmp ("fitheight", value))
|
||||
view->desktop_image_scale_method =
|
||||
GRUB_VIDEO_BITMAP_SELECTION_METHOD_FITHEIGHT;
|
||||
else
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"Unsupported scale method: %s",
|
||||
value);
|
||||
}
|
||||
else if (! grub_strcmp ("desktop-image-h-align", name))
|
||||
{
|
||||
if (! grub_strcmp ("left", value))
|
||||
view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_LEFT;
|
||||
else if (! grub_strcmp ("center", value))
|
||||
view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_CENTER;
|
||||
else if (! grub_strcmp ("right", value))
|
||||
view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_RIGHT;
|
||||
else
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"Unsupported horizontal align method: %s",
|
||||
value);
|
||||
}
|
||||
else if (! grub_strcmp ("desktop-image-v-align", name))
|
||||
{
|
||||
if (! grub_strcmp ("top", value))
|
||||
view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_TOP;
|
||||
else if (! grub_strcmp ("center", value))
|
||||
view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_CENTER;
|
||||
else if (! grub_strcmp ("bottom", value))
|
||||
view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_BOTTOM;
|
||||
else
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"Unsupported vertical align method: %s",
|
||||
value);
|
||||
}
|
||||
else if (! grub_strcmp ("desktop-color", name))
|
||||
grub_video_parse_color (value, &view->desktop_color);
|
||||
else if (! grub_strcmp ("terminal-box", name))
|
||||
{
|
||||
grub_err_t err;
|
||||
err = grub_gui_recreate_box (&view->terminal_box, value, theme_dir);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
}
|
||||
else if (! grub_strcmp ("terminal-border", name))
|
||||
{
|
||||
view->terminal_border = grub_strtoul (value, 0, 10);
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
}
|
||||
else if (! grub_strcmp ("terminal-left", name))
|
||||
{
|
||||
unsigned int tmp;
|
||||
int err = theme_get_unsigned_int_from_proportional (value,
|
||||
view->screen.width,
|
||||
&tmp);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
view->terminal_rect.x = tmp;
|
||||
}
|
||||
else if (! grub_strcmp ("terminal-top", name))
|
||||
{
|
||||
unsigned int tmp;
|
||||
int err = theme_get_unsigned_int_from_proportional (value,
|
||||
view->screen.height,
|
||||
&tmp);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
view->terminal_rect.y = tmp;
|
||||
}
|
||||
else if (! grub_strcmp ("terminal-width", name))
|
||||
{
|
||||
unsigned int tmp;
|
||||
int err = theme_get_unsigned_int_from_proportional (value,
|
||||
view->screen.width,
|
||||
&tmp);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
view->terminal_rect.width = tmp;
|
||||
}
|
||||
else if (! grub_strcmp ("terminal-height", name))
|
||||
{
|
||||
unsigned int tmp;
|
||||
int err = theme_get_unsigned_int_from_proportional (value,
|
||||
view->screen.height,
|
||||
&tmp);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
view->terminal_rect.height = tmp;
|
||||
}
|
||||
else if (! grub_strcmp ("title-text", name))
|
||||
{
|
||||
grub_free (view->title_text);
|
||||
view->title_text = grub_strdup (value);
|
||||
if (! view->title_text)
|
||||
return grub_errno;
|
||||
}
|
||||
else
|
||||
{
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"%s:%d:%d unknown property `%s'",
|
||||
filename, line_num, col_num, name);
|
||||
}
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
struct parsebuf
|
||||
{
|
||||
char *buf;
|
||||
int pos;
|
||||
int len;
|
||||
int line_num;
|
||||
int col_num;
|
||||
const char *filename;
|
||||
char *theme_dir;
|
||||
grub_gfxmenu_view_t view;
|
||||
};
|
||||
|
||||
static int
|
||||
has_more (struct parsebuf *p)
|
||||
{
|
||||
return p->pos < p->len;
|
||||
}
|
||||
|
||||
static int
|
||||
read_char (struct parsebuf *p)
|
||||
{
|
||||
if (has_more (p))
|
||||
{
|
||||
char c;
|
||||
c = p->buf[p->pos++];
|
||||
if (c == '\n')
|
||||
{
|
||||
p->line_num++;
|
||||
p->col_num = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
p->col_num++;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
peek_char (struct parsebuf *p)
|
||||
{
|
||||
if (has_more (p))
|
||||
return p->buf[p->pos];
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
is_whitespace (char c)
|
||||
{
|
||||
return (c == ' '
|
||||
|| c == '\t'
|
||||
|| c == '\r'
|
||||
|| c == '\n'
|
||||
|| c == '\f');
|
||||
}
|
||||
|
||||
static void
|
||||
skip_whitespace (struct parsebuf *p)
|
||||
{
|
||||
while (has_more (p) && is_whitespace(peek_char (p)))
|
||||
read_char (p);
|
||||
}
|
||||
|
||||
static void
|
||||
advance_to_next_line (struct parsebuf *p)
|
||||
{
|
||||
int c;
|
||||
|
||||
/* Eat characters up to the newline. */
|
||||
do
|
||||
{
|
||||
c = read_char (p);
|
||||
}
|
||||
while (c != -1 && c != '\n');
|
||||
}
|
||||
|
||||
static int
|
||||
is_identifier_char (int c)
|
||||
{
|
||||
return (c != -1
|
||||
&& (grub_isalpha(c)
|
||||
|| grub_isdigit(c)
|
||||
|| c == '_'
|
||||
|| c == '-'));
|
||||
}
|
||||
|
||||
static char *
|
||||
read_identifier (struct parsebuf *p)
|
||||
{
|
||||
/* Index of the first character of the identifier in p->buf. */
|
||||
int start;
|
||||
/* Next index after the last character of the identifer in p->buf. */
|
||||
int end;
|
||||
|
||||
skip_whitespace (p);
|
||||
|
||||
/* Capture the start of the identifier. */
|
||||
start = p->pos;
|
||||
|
||||
/* Scan for the end. */
|
||||
while (is_identifier_char (peek_char (p)))
|
||||
read_char (p);
|
||||
end = p->pos;
|
||||
|
||||
if (end - start < 1)
|
||||
return 0;
|
||||
|
||||
return grub_new_substring (p->buf, start, end);
|
||||
}
|
||||
|
||||
static char *
|
||||
read_expression (struct parsebuf *p)
|
||||
{
|
||||
int start;
|
||||
int end;
|
||||
|
||||
skip_whitespace (p);
|
||||
if (peek_char (p) == '"')
|
||||
{
|
||||
/* Read as a quoted string.
|
||||
The quotation marks are not included in the expression value. */
|
||||
/* Skip opening quotation mark. */
|
||||
read_char (p);
|
||||
start = p->pos;
|
||||
while (has_more (p) && peek_char (p) != '"')
|
||||
read_char (p);
|
||||
end = p->pos;
|
||||
/* Skip the terminating quotation mark. */
|
||||
read_char (p);
|
||||
}
|
||||
else if (peek_char (p) == '(')
|
||||
{
|
||||
/* Read as a parenthesized string -- for tuples/coordinates. */
|
||||
/* The parentheses are included in the expression value. */
|
||||
int c;
|
||||
|
||||
start = p->pos;
|
||||
do
|
||||
{
|
||||
c = read_char (p);
|
||||
}
|
||||
while (c != -1 && c != ')');
|
||||
end = p->pos;
|
||||
}
|
||||
else if (has_more (p))
|
||||
{
|
||||
/* Read as a single word -- for numeric values or words without
|
||||
whitespace. */
|
||||
start = p->pos;
|
||||
while (has_more (p) && ! is_whitespace (peek_char (p)))
|
||||
read_char (p);
|
||||
end = p->pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The end of the theme file has been reached. */
|
||||
grub_error (GRUB_ERR_IO, "%s:%d:%d expression expected in theme file",
|
||||
p->filename, p->line_num, p->col_num);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return grub_new_substring (p->buf, start, end);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
parse_proportional_spec (const char *value, signed *abs, grub_fixed_signed_t *prop)
|
||||
{
|
||||
signed num;
|
||||
const char *ptr;
|
||||
int sig = 0;
|
||||
*abs = 0;
|
||||
*prop = 0;
|
||||
ptr = value;
|
||||
while (*ptr)
|
||||
{
|
||||
sig = 0;
|
||||
|
||||
while (*ptr == '-' || *ptr == '+')
|
||||
{
|
||||
if (*ptr == '-')
|
||||
sig = !sig;
|
||||
ptr++;
|
||||
}
|
||||
|
||||
num = grub_strtoul (ptr, (char **) &ptr, 0);
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
if (sig)
|
||||
num = -num;
|
||||
if (*ptr == '%')
|
||||
{
|
||||
*prop += grub_fixed_fsf_divide (grub_signed_to_fixed (num), 100);
|
||||
ptr++;
|
||||
}
|
||||
else
|
||||
*abs += num;
|
||||
}
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
|
||||
/* Read a GUI object specification from the theme file.
|
||||
Any components created will be added to the GUI container PARENT. */
|
||||
static grub_err_t
|
||||
read_object (struct parsebuf *p, grub_gui_container_t parent)
|
||||
{
|
||||
grub_video_rect_t bounds;
|
||||
|
||||
char *name;
|
||||
name = read_identifier (p);
|
||||
if (! name)
|
||||
goto cleanup;
|
||||
|
||||
grub_gui_component_t component = 0;
|
||||
if (grub_strcmp (name, "label") == 0)
|
||||
{
|
||||
component = grub_gui_label_new ();
|
||||
}
|
||||
else if (grub_strcmp (name, "image") == 0)
|
||||
{
|
||||
component = grub_gui_image_new ();
|
||||
}
|
||||
else if (grub_strcmp (name, "vbox") == 0)
|
||||
{
|
||||
component = (grub_gui_component_t) grub_gui_vbox_new ();
|
||||
}
|
||||
else if (grub_strcmp (name, "hbox") == 0)
|
||||
{
|
||||
component = (grub_gui_component_t) grub_gui_hbox_new ();
|
||||
}
|
||||
else if (grub_strcmp (name, "canvas") == 0)
|
||||
{
|
||||
component = (grub_gui_component_t) grub_gui_canvas_new ();
|
||||
}
|
||||
else if (grub_strcmp (name, "progress_bar") == 0)
|
||||
{
|
||||
component = grub_gui_progress_bar_new ();
|
||||
}
|
||||
else if (grub_strcmp (name, "circular_progress") == 0)
|
||||
{
|
||||
component = grub_gui_circular_progress_new ();
|
||||
}
|
||||
else if (grub_strcmp (name, "boot_menu") == 0)
|
||||
{
|
||||
component = grub_gui_list_new ();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unknown type. */
|
||||
grub_error (GRUB_ERR_IO, "%s:%d:%d unknown object type `%s'",
|
||||
p->filename, p->line_num, p->col_num, name);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (! component)
|
||||
goto cleanup;
|
||||
|
||||
/* Inform the component about the theme so it can find its resources. */
|
||||
component->ops->set_property (component, "theme_dir", p->theme_dir);
|
||||
component->ops->set_property (component, "theme_path", p->filename);
|
||||
|
||||
/* Add the component as a child of PARENT. */
|
||||
bounds.x = 0;
|
||||
bounds.y = 0;
|
||||
bounds.width = -1;
|
||||
bounds.height = -1;
|
||||
component->ops->set_bounds (component, &bounds);
|
||||
parent->ops->add (parent, component);
|
||||
|
||||
skip_whitespace (p);
|
||||
if (read_char (p) != '{')
|
||||
{
|
||||
grub_error (GRUB_ERR_IO,
|
||||
"%s:%d:%d expected `{' after object type name `%s'",
|
||||
p->filename, p->line_num, p->col_num, name);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
while (has_more (p))
|
||||
{
|
||||
skip_whitespace (p);
|
||||
|
||||
/* Check whether the end has been encountered. */
|
||||
if (peek_char (p) == '}')
|
||||
{
|
||||
/* Skip the closing brace. */
|
||||
read_char (p);
|
||||
break;
|
||||
}
|
||||
|
||||
if (peek_char (p) == '#')
|
||||
{
|
||||
/* Skip comments. */
|
||||
advance_to_next_line (p);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (peek_char (p) == '+')
|
||||
{
|
||||
/* Skip the '+'. */
|
||||
read_char (p);
|
||||
|
||||
/* Check whether this component is a container. */
|
||||
if (component->ops->is_instance (component, "container"))
|
||||
{
|
||||
/* Read the sub-object recursively and add it as a child. */
|
||||
if (read_object (p, (grub_gui_container_t) component) != 0)
|
||||
goto cleanup;
|
||||
/* After reading the sub-object, resume parsing, expecting
|
||||
another property assignment or sub-object definition. */
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_error (GRUB_ERR_IO,
|
||||
"%s:%d:%d attempted to add object to non-container",
|
||||
p->filename, p->line_num, p->col_num);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
char *property;
|
||||
property = read_identifier (p);
|
||||
if (! property)
|
||||
{
|
||||
grub_error (GRUB_ERR_IO, "%s:%d:%d identifier expected in theme file",
|
||||
p->filename, p->line_num, p->col_num);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
skip_whitespace (p);
|
||||
if (read_char (p) != '=')
|
||||
{
|
||||
grub_error (GRUB_ERR_IO,
|
||||
"%s:%d:%d expected `=' after property name `%s'",
|
||||
p->filename, p->line_num, p->col_num, property);
|
||||
grub_free (property);
|
||||
goto cleanup;
|
||||
}
|
||||
skip_whitespace (p);
|
||||
|
||||
char *value;
|
||||
value = read_expression (p);
|
||||
if (! value)
|
||||
{
|
||||
grub_free (property);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Handle the property value. */
|
||||
if (grub_strcmp (property, "left") == 0)
|
||||
parse_proportional_spec (value, &component->x, &component->xfrac);
|
||||
else if (grub_strcmp (property, "top") == 0)
|
||||
parse_proportional_spec (value, &component->y, &component->yfrac);
|
||||
else if (grub_strcmp (property, "width") == 0)
|
||||
parse_proportional_spec (value, &component->w, &component->wfrac);
|
||||
else if (grub_strcmp (property, "height") == 0)
|
||||
parse_proportional_spec (value, &component->h, &component->hfrac);
|
||||
else
|
||||
/* General property handling. */
|
||||
component->ops->set_property (component, property, value);
|
||||
|
||||
grub_free (value);
|
||||
grub_free (property);
|
||||
if (grub_errno != GRUB_ERR_NONE)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
grub_free (name);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
read_property (struct parsebuf *p)
|
||||
{
|
||||
char *name;
|
||||
|
||||
/* Read the property name. */
|
||||
name = read_identifier (p);
|
||||
if (! name)
|
||||
{
|
||||
advance_to_next_line (p);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
/* Skip whitespace before separator. */
|
||||
skip_whitespace (p);
|
||||
|
||||
/* Read separator. */
|
||||
if (read_char (p) != ':')
|
||||
{
|
||||
grub_error (GRUB_ERR_IO,
|
||||
"%s:%d:%d missing separator after property name `%s'",
|
||||
p->filename, p->line_num, p->col_num, name);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Skip whitespace after separator. */
|
||||
skip_whitespace (p);
|
||||
|
||||
/* Get the value based on its type. */
|
||||
if (peek_char (p) == '"')
|
||||
{
|
||||
/* String value (e.g., '"My string"'). */
|
||||
char *value = read_expression (p);
|
||||
if (! value)
|
||||
{
|
||||
grub_error (GRUB_ERR_IO, "%s:%d:%d missing property value",
|
||||
p->filename, p->line_num, p->col_num);
|
||||
goto done;
|
||||
}
|
||||
/* If theme_set_string results in an error, grub_errno will be returned
|
||||
below. */
|
||||
theme_set_string (p->view, name, value, p->theme_dir,
|
||||
p->filename, p->line_num, p->col_num);
|
||||
grub_free (value);
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_error (GRUB_ERR_IO,
|
||||
"%s:%d:%d property value invalid; "
|
||||
"enclose literal values in quotes (\")",
|
||||
p->filename, p->line_num, p->col_num);
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
grub_free (name);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
/* Set properties on the view based on settings from the specified
|
||||
theme file. */
|
||||
grub_err_t
|
||||
grub_gfxmenu_view_load_theme (grub_gfxmenu_view_t view, const char *theme_path)
|
||||
{
|
||||
grub_file_t file;
|
||||
struct parsebuf p;
|
||||
|
||||
p.view = view;
|
||||
p.theme_dir = grub_get_dirname (theme_path);
|
||||
|
||||
file = grub_file_open (theme_path, GRUB_FILE_TYPE_THEME);
|
||||
if (! file)
|
||||
{
|
||||
grub_free (p.theme_dir);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
p.len = grub_file_size (file);
|
||||
p.buf = grub_malloc (p.len + 4096);
|
||||
p.pos = 0;
|
||||
p.line_num = 1;
|
||||
p.col_num = 1;
|
||||
p.filename = theme_path;
|
||||
if (! p.buf)
|
||||
{
|
||||
grub_file_close (file);
|
||||
grub_free (p.theme_dir);
|
||||
return grub_errno;
|
||||
}
|
||||
if (grub_file_read (file, p.buf, p.len) != p.len)
|
||||
{
|
||||
grub_free (p.buf);
|
||||
grub_file_close (file);
|
||||
grub_free (p.theme_dir);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
{
|
||||
const char *checkret = grub_env_get("VTOY_CHKDEV_RESULT_STRING");
|
||||
if (checkret == NULL || checkret[0] != '0')
|
||||
{
|
||||
p.len += grub_snprintf(p.buf + p.len, 4096, "\n+ hbox{\n left = 1%%\n top = 90%%\n"
|
||||
" + label {text = \"[Unofficial Ventoy]\" color = \"red\" align = \"left\"}\n"
|
||||
"}\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (view->canvas)
|
||||
view->canvas->component.ops->destroy (view->canvas);
|
||||
|
||||
view->canvas = grub_gui_canvas_new ();
|
||||
if (!view->canvas)
|
||||
goto fail;
|
||||
((grub_gui_component_t) view->canvas)
|
||||
->ops->set_bounds ((grub_gui_component_t) view->canvas,
|
||||
&view->screen);
|
||||
|
||||
while (has_more (&p))
|
||||
{
|
||||
/* Skip comments (lines beginning with #). */
|
||||
if (peek_char (&p) == '#')
|
||||
{
|
||||
advance_to_next_line (&p);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Find the first non-whitespace character. */
|
||||
skip_whitespace (&p);
|
||||
|
||||
/* Handle the content. */
|
||||
if (peek_char (&p) == '+')
|
||||
{
|
||||
/* Skip the '+'. */
|
||||
read_char (&p);
|
||||
read_object (&p, view->canvas);
|
||||
}
|
||||
else
|
||||
{
|
||||
read_property (&p);
|
||||
}
|
||||
|
||||
if (grub_errno != GRUB_ERR_NONE)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Set the new theme path. */
|
||||
grub_free (view->theme_path);
|
||||
view->theme_path = grub_strdup (theme_path);
|
||||
goto cleanup;
|
||||
|
||||
fail:
|
||||
if (view->canvas)
|
||||
{
|
||||
view->canvas->component.ops->destroy (view->canvas);
|
||||
view->canvas = 0;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
grub_free (p.buf);
|
||||
grub_file_close (file);
|
||||
grub_free (p.theme_dir);
|
||||
return grub_errno;
|
||||
}
|
647
GRUB2/MOD_SRC/grub-2.04/grub-core/gfxmenu/view.c
Normal file
647
GRUB2/MOD_SRC/grub-2.04/grub-core/gfxmenu/view.c
Normal file
@ -0,0 +1,647 @@
|
||||
/* view.c - Graphical menu interface MVC view. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/types.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/video.h>
|
||||
#include <grub/gfxterm.h>
|
||||
#include <grub/bitmap.h>
|
||||
#include <grub/bitmap_scale.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/gfxwidgets.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/menu.h>
|
||||
#include <grub/menu_viewer.h>
|
||||
#include <grub/gfxmenu_view.h>
|
||||
#include <grub/gui_string_util.h>
|
||||
#include <grub/icon_manager.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static void
|
||||
init_terminal (grub_gfxmenu_view_t view);
|
||||
static void
|
||||
init_background (grub_gfxmenu_view_t view);
|
||||
static grub_gfxmenu_view_t term_view;
|
||||
|
||||
/* Create a new view object, loading the theme specified by THEME_PATH and
|
||||
associating MODEL with the view. */
|
||||
grub_gfxmenu_view_t
|
||||
grub_gfxmenu_view_new (const char *theme_path,
|
||||
int width, int height)
|
||||
{
|
||||
grub_gfxmenu_view_t view;
|
||||
grub_font_t default_font;
|
||||
grub_video_rgba_color_t default_fg_color;
|
||||
grub_video_rgba_color_t default_bg_color;
|
||||
|
||||
view = grub_malloc (sizeof (*view));
|
||||
if (! view)
|
||||
return 0;
|
||||
|
||||
while (grub_gfxmenu_timeout_notifications)
|
||||
{
|
||||
struct grub_gfxmenu_timeout_notify *p;
|
||||
p = grub_gfxmenu_timeout_notifications;
|
||||
grub_gfxmenu_timeout_notifications = grub_gfxmenu_timeout_notifications->next;
|
||||
grub_free (p);
|
||||
}
|
||||
|
||||
view->screen.x = 0;
|
||||
view->screen.y = 0;
|
||||
view->screen.width = width;
|
||||
view->screen.height = height;
|
||||
|
||||
view->need_to_check_sanity = 1;
|
||||
view->terminal_border = 3;
|
||||
view->terminal_rect.width = view->screen.width * 7 / 10;
|
||||
view->terminal_rect.height = view->screen.height * 7 / 10;
|
||||
view->terminal_rect.x = view->screen.x + (view->screen.width
|
||||
- view->terminal_rect.width) / 2;
|
||||
view->terminal_rect.y = view->screen.y + (view->screen.height
|
||||
- view->terminal_rect.height) / 2;
|
||||
|
||||
default_font = grub_font_get ("Unknown Regular 16");
|
||||
default_fg_color = grub_video_rgba_color_rgb (0, 0, 0);
|
||||
default_bg_color = grub_video_rgba_color_rgb (255, 255, 255);
|
||||
|
||||
view->canvas = 0;
|
||||
|
||||
view->title_font = default_font;
|
||||
view->message_font = default_font;
|
||||
view->terminal_font_name = grub_strdup ("Fixed 10");
|
||||
view->title_color = default_fg_color;
|
||||
view->message_color = default_bg_color;
|
||||
view->message_bg_color = default_fg_color;
|
||||
view->raw_desktop_image = 0;
|
||||
view->scaled_desktop_image = 0;
|
||||
view->desktop_image_scale_method = GRUB_VIDEO_BITMAP_SELECTION_METHOD_STRETCH;
|
||||
view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_CENTER;
|
||||
view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_CENTER;
|
||||
view->desktop_color = default_bg_color;
|
||||
view->terminal_box = grub_gfxmenu_create_box (0, 0);
|
||||
view->title_text = grub_strdup (_("GRUB Boot Menu"));
|
||||
view->progress_message_text = 0;
|
||||
view->theme_path = 0;
|
||||
|
||||
/* Set the timeout bar's frame. */
|
||||
view->progress_message_frame.width = view->screen.width * 4 / 5;
|
||||
view->progress_message_frame.height = 50;
|
||||
view->progress_message_frame.x = view->screen.x
|
||||
+ (view->screen.width - view->progress_message_frame.width) / 2;
|
||||
view->progress_message_frame.y = view->screen.y
|
||||
+ view->screen.height - 90 - 20 - view->progress_message_frame.height;
|
||||
|
||||
if (grub_gfxmenu_view_load_theme (view, theme_path) != 0)
|
||||
{
|
||||
grub_gfxmenu_view_destroy (view);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
/* Destroy the view object. All used memory is freed. */
|
||||
void
|
||||
grub_gfxmenu_view_destroy (grub_gfxmenu_view_t view)
|
||||
{
|
||||
if (!view)
|
||||
return;
|
||||
while (grub_gfxmenu_timeout_notifications)
|
||||
{
|
||||
struct grub_gfxmenu_timeout_notify *p;
|
||||
p = grub_gfxmenu_timeout_notifications;
|
||||
grub_gfxmenu_timeout_notifications = grub_gfxmenu_timeout_notifications->next;
|
||||
grub_free (p);
|
||||
}
|
||||
grub_video_bitmap_destroy (view->raw_desktop_image);
|
||||
grub_video_bitmap_destroy (view->scaled_desktop_image);
|
||||
if (view->terminal_box)
|
||||
view->terminal_box->destroy (view->terminal_box);
|
||||
grub_free (view->terminal_font_name);
|
||||
grub_free (view->title_text);
|
||||
grub_free (view->progress_message_text);
|
||||
grub_free (view->theme_path);
|
||||
if (view->canvas)
|
||||
view->canvas->component.ops->destroy (view->canvas);
|
||||
grub_free (view);
|
||||
}
|
||||
|
||||
static void
|
||||
redraw_background (grub_gfxmenu_view_t view,
|
||||
const grub_video_rect_t *bounds)
|
||||
{
|
||||
if (view->scaled_desktop_image)
|
||||
{
|
||||
struct grub_video_bitmap *img = view->scaled_desktop_image;
|
||||
grub_video_blit_bitmap (img, GRUB_VIDEO_BLIT_REPLACE,
|
||||
bounds->x, bounds->y,
|
||||
bounds->x - view->screen.x,
|
||||
bounds->y - view->screen.y,
|
||||
bounds->width, bounds->height);
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_video_fill_rect (grub_video_map_rgba_color (view->desktop_color),
|
||||
bounds->x, bounds->y,
|
||||
bounds->width, bounds->height);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
draw_title (grub_gfxmenu_view_t view)
|
||||
{
|
||||
if (! view->title_text)
|
||||
return;
|
||||
|
||||
/* Center the title. */
|
||||
int title_width = grub_font_get_string_width (view->title_font,
|
||||
view->title_text);
|
||||
int x = (view->screen.width - title_width) / 2;
|
||||
int y = 40 + grub_font_get_ascent (view->title_font);
|
||||
grub_font_draw_string (view->title_text,
|
||||
view->title_font,
|
||||
grub_video_map_rgba_color (view->title_color),
|
||||
x, y);
|
||||
}
|
||||
|
||||
struct progress_value_data
|
||||
{
|
||||
int visible;
|
||||
int start;
|
||||
int end;
|
||||
int value;
|
||||
};
|
||||
|
||||
struct grub_gfxmenu_timeout_notify *grub_gfxmenu_timeout_notifications;
|
||||
|
||||
static void
|
||||
update_timeouts (int visible, int start, int value, int end)
|
||||
{
|
||||
struct grub_gfxmenu_timeout_notify *cur;
|
||||
|
||||
for (cur = grub_gfxmenu_timeout_notifications; cur; cur = cur->next)
|
||||
cur->set_state (cur->self, visible, start, value, end);
|
||||
}
|
||||
|
||||
static void
|
||||
redraw_timeouts (struct grub_gfxmenu_view *view)
|
||||
{
|
||||
struct grub_gfxmenu_timeout_notify *cur;
|
||||
|
||||
for (cur = grub_gfxmenu_timeout_notifications; cur; cur = cur->next)
|
||||
{
|
||||
grub_video_rect_t bounds;
|
||||
cur->self->ops->get_bounds (cur->self, &bounds);
|
||||
grub_video_set_area_status (GRUB_VIDEO_AREA_ENABLED);
|
||||
grub_gfxmenu_view_redraw (view, &bounds);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
grub_gfxmenu_print_timeout (int timeout, void *data)
|
||||
{
|
||||
struct grub_gfxmenu_view *view = data;
|
||||
|
||||
if (view->first_timeout == -1)
|
||||
view->first_timeout = timeout;
|
||||
|
||||
update_timeouts (1, -view->first_timeout, -timeout, 0);
|
||||
redraw_timeouts (view);
|
||||
grub_video_swap_buffers ();
|
||||
if (view->double_repaint)
|
||||
redraw_timeouts (view);
|
||||
}
|
||||
|
||||
void
|
||||
grub_gfxmenu_clear_timeout (void *data)
|
||||
{
|
||||
struct grub_gfxmenu_view *view = data;
|
||||
|
||||
update_timeouts (0, 1, 0, 0);
|
||||
redraw_timeouts (view);
|
||||
grub_video_swap_buffers ();
|
||||
if (view->double_repaint)
|
||||
redraw_timeouts (view);
|
||||
}
|
||||
|
||||
static void
|
||||
update_menu_visit (grub_gui_component_t component,
|
||||
void *userdata)
|
||||
{
|
||||
grub_gfxmenu_view_t view;
|
||||
view = userdata;
|
||||
if (component->ops->is_instance (component, "list"))
|
||||
{
|
||||
grub_gui_list_t list = (grub_gui_list_t) component;
|
||||
list->ops->set_view_info (list, view);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update any boot menu components with the current menu model and
|
||||
theme path. */
|
||||
static void
|
||||
update_menu_components (grub_gfxmenu_view_t view)
|
||||
{
|
||||
grub_gui_iterate_recursively ((grub_gui_component_t) view->canvas,
|
||||
update_menu_visit, view);
|
||||
}
|
||||
|
||||
static void
|
||||
refresh_menu_visit (grub_gui_component_t component,
|
||||
void *userdata)
|
||||
{
|
||||
grub_gfxmenu_view_t view;
|
||||
view = userdata;
|
||||
if (component->ops->is_instance (component, "list"))
|
||||
{
|
||||
grub_gui_list_t list = (grub_gui_list_t) component;
|
||||
list->ops->refresh_list (list, view);
|
||||
}
|
||||
}
|
||||
|
||||
/* Refresh list information (useful for submenus) */
|
||||
static void
|
||||
refresh_menu_components (grub_gfxmenu_view_t view)
|
||||
{
|
||||
grub_gui_iterate_recursively ((grub_gui_component_t) view->canvas,
|
||||
refresh_menu_visit, view);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_message (grub_gfxmenu_view_t view)
|
||||
{
|
||||
char *text = view->progress_message_text;
|
||||
grub_video_rect_t f = view->progress_message_frame;
|
||||
if (! text)
|
||||
return;
|
||||
|
||||
grub_font_t font = view->message_font;
|
||||
grub_video_color_t color = grub_video_map_rgba_color (view->message_color);
|
||||
|
||||
/* Border. */
|
||||
grub_video_fill_rect (color,
|
||||
f.x-1, f.y-1, f.width+2, f.height+2);
|
||||
/* Fill. */
|
||||
grub_video_fill_rect (grub_video_map_rgba_color (view->message_bg_color),
|
||||
f.x, f.y, f.width, f.height);
|
||||
|
||||
/* Center the text. */
|
||||
int text_width = grub_font_get_string_width (font, text);
|
||||
int x = f.x + (f.width - text_width) / 2;
|
||||
int y = (f.y + (f.height - grub_font_get_descent (font)) / 2
|
||||
+ grub_font_get_ascent (font) / 2);
|
||||
grub_font_draw_string (text, font, color, x, y);
|
||||
}
|
||||
|
||||
void
|
||||
grub_gfxmenu_view_redraw (grub_gfxmenu_view_t view,
|
||||
const grub_video_rect_t *region)
|
||||
{
|
||||
if (grub_video_have_common_points (&view->terminal_rect, region))
|
||||
grub_gfxterm_schedule_repaint ();
|
||||
|
||||
grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
|
||||
grub_video_area_status_t area_status;
|
||||
grub_video_get_area_status (&area_status);
|
||||
if (area_status == GRUB_VIDEO_AREA_ENABLED)
|
||||
grub_video_set_region (region->x, region->y,
|
||||
region->width, region->height);
|
||||
|
||||
redraw_background (view, region);
|
||||
if (view->canvas)
|
||||
view->canvas->component.ops->paint (view->canvas, region);
|
||||
draw_title (view);
|
||||
if (grub_video_have_common_points (&view->progress_message_frame, region))
|
||||
draw_message (view);
|
||||
|
||||
if (area_status == GRUB_VIDEO_AREA_ENABLED)
|
||||
grub_video_set_area_status (GRUB_VIDEO_AREA_ENABLED);
|
||||
}
|
||||
|
||||
void
|
||||
grub_gfxmenu_view_draw (grub_gfxmenu_view_t view)
|
||||
{
|
||||
init_terminal (view);
|
||||
|
||||
init_background (view);
|
||||
|
||||
/* Clear the screen; there may be garbage left over in video memory. */
|
||||
grub_video_fill_rect (grub_video_map_rgb (0, 0, 0),
|
||||
view->screen.x, view->screen.y,
|
||||
view->screen.width, view->screen.height);
|
||||
grub_video_swap_buffers ();
|
||||
if (view->double_repaint)
|
||||
grub_video_fill_rect (grub_video_map_rgb (0, 0, 0),
|
||||
view->screen.x, view->screen.y,
|
||||
view->screen.width, view->screen.height);
|
||||
|
||||
refresh_menu_components (view);
|
||||
update_menu_components (view);
|
||||
|
||||
grub_video_set_area_status (GRUB_VIDEO_AREA_DISABLED);
|
||||
grub_gfxmenu_view_redraw (view, &view->screen);
|
||||
grub_video_swap_buffers ();
|
||||
if (view->double_repaint)
|
||||
{
|
||||
grub_video_set_area_status (GRUB_VIDEO_AREA_DISABLED);
|
||||
grub_gfxmenu_view_redraw (view, &view->screen);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
redraw_menu_visit (grub_gui_component_t component,
|
||||
void *userdata)
|
||||
{
|
||||
grub_gfxmenu_view_t view;
|
||||
view = userdata;
|
||||
if (component->ops->is_instance (component, "list"))
|
||||
{
|
||||
grub_video_rect_t bounds;
|
||||
|
||||
component->ops->get_bounds (component, &bounds);
|
||||
grub_video_set_area_status (GRUB_VIDEO_AREA_ENABLED);
|
||||
grub_gfxmenu_view_redraw (view, &bounds);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
grub_gfxmenu_redraw_menu (grub_gfxmenu_view_t view)
|
||||
{
|
||||
update_menu_components (view);
|
||||
|
||||
grub_gui_iterate_recursively ((grub_gui_component_t) view->canvas,
|
||||
redraw_menu_visit, view);
|
||||
grub_video_swap_buffers ();
|
||||
if (view->double_repaint)
|
||||
{
|
||||
grub_gui_iterate_recursively ((grub_gui_component_t) view->canvas,
|
||||
redraw_menu_visit, view);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
grub_gfxmenu_set_chosen_entry (int entry, void *data)
|
||||
{
|
||||
grub_gfxmenu_view_t view = data;
|
||||
|
||||
view->selected = entry;
|
||||
grub_gfxmenu_redraw_menu (view);
|
||||
}
|
||||
|
||||
static void
|
||||
grub_gfxmenu_draw_terminal_box (void)
|
||||
{
|
||||
grub_gfxmenu_box_t term_box;
|
||||
|
||||
term_box = term_view->terminal_box;
|
||||
if (!term_box)
|
||||
return;
|
||||
|
||||
grub_video_set_area_status (GRUB_VIDEO_AREA_DISABLED);
|
||||
|
||||
term_box->set_content_size (term_box, term_view->terminal_rect.width,
|
||||
term_view->terminal_rect.height);
|
||||
|
||||
term_box->draw (term_box,
|
||||
term_view->terminal_rect.x - term_box->get_left_pad (term_box),
|
||||
term_view->terminal_rect.y - term_box->get_top_pad (term_box));
|
||||
}
|
||||
|
||||
static void
|
||||
get_min_terminal (grub_font_t terminal_font,
|
||||
unsigned int border_width,
|
||||
unsigned int *min_terminal_width,
|
||||
unsigned int *min_terminal_height)
|
||||
{
|
||||
struct grub_font_glyph *glyph;
|
||||
glyph = grub_font_get_glyph (terminal_font, 'M');
|
||||
*min_terminal_width = (glyph? glyph->device_width : 8) * 80
|
||||
+ 2 * border_width;
|
||||
*min_terminal_height = grub_font_get_max_char_height (terminal_font) * 24
|
||||
+ 2 * border_width;
|
||||
}
|
||||
|
||||
static void
|
||||
terminal_sanity_check (grub_gfxmenu_view_t view)
|
||||
{
|
||||
if (!view->need_to_check_sanity)
|
||||
return;
|
||||
|
||||
/* terminal_font was checked before in the init_terminal function. */
|
||||
grub_font_t terminal_font = grub_font_get (view->terminal_font_name);
|
||||
|
||||
/* Non-negative numbers below. */
|
||||
int scr_x = view->screen.x;
|
||||
int scr_y = view->screen.y;
|
||||
int scr_width = view->screen.width;
|
||||
int scr_height = view->screen.height;
|
||||
int term_x = view->terminal_rect.x;
|
||||
int term_y = view->terminal_rect.y;
|
||||
int term_width = view->terminal_rect.width;
|
||||
int term_height = view->terminal_rect.height;
|
||||
|
||||
/* Check that border_width isn't too big. */
|
||||
unsigned int border_width = view->terminal_border;
|
||||
unsigned int min_terminal_width;
|
||||
unsigned int min_terminal_height;
|
||||
get_min_terminal (terminal_font, border_width,
|
||||
&min_terminal_width, &min_terminal_height);
|
||||
if (border_width > 3 && ((int) min_terminal_width >= scr_width
|
||||
|| (int) min_terminal_height >= scr_height))
|
||||
{
|
||||
border_width = 3;
|
||||
get_min_terminal (terminal_font, border_width,
|
||||
&min_terminal_width, &min_terminal_height);
|
||||
}
|
||||
|
||||
/* Sanity checks. */
|
||||
if (term_width > scr_width)
|
||||
term_width = scr_width;
|
||||
if (term_height > scr_height)
|
||||
term_height = scr_height;
|
||||
|
||||
if (scr_width <= (int) min_terminal_width
|
||||
|| scr_height <= (int) min_terminal_height)
|
||||
{
|
||||
/* The screen resulution is too low. Use all space, except a small border
|
||||
to show the user, that it is a window. Then center the window. */
|
||||
term_width = scr_width - 6 * border_width;
|
||||
term_height = scr_height - 6 * border_width;
|
||||
term_x = scr_x + (scr_width - term_width) / 2;
|
||||
term_y = scr_y + (scr_height - term_height) / 2;
|
||||
}
|
||||
else if (term_width < (int) min_terminal_width
|
||||
|| term_height < (int) min_terminal_height)
|
||||
{
|
||||
/* The screen resolution is big enough. Make sure, that terminal screen
|
||||
dimensions aren't less than minimal values. Then center the window. */
|
||||
term_width = (int) min_terminal_width;
|
||||
term_height = (int) min_terminal_height;
|
||||
term_x = scr_x + (scr_width - term_width) / 2;
|
||||
term_y = scr_y + (scr_height - term_height) / 2;
|
||||
}
|
||||
|
||||
/* At this point w and h are satisfying. */
|
||||
if (term_x + term_width > scr_width)
|
||||
term_x = scr_width - term_width;
|
||||
if (term_y + term_height > scr_height)
|
||||
term_y = scr_height - term_height;
|
||||
|
||||
/* Write down corrected data. */
|
||||
view->terminal_rect.x = (unsigned int) term_x;
|
||||
view->terminal_rect.y = (unsigned int) term_y;
|
||||
view->terminal_rect.width = (unsigned int) term_width;
|
||||
view->terminal_rect.height = (unsigned int) term_height;
|
||||
view->terminal_border = border_width;
|
||||
|
||||
view->need_to_check_sanity = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
init_terminal (grub_gfxmenu_view_t view)
|
||||
{
|
||||
grub_font_t terminal_font;
|
||||
|
||||
terminal_font = grub_font_get (view->terminal_font_name);
|
||||
if (!terminal_font)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_FONT, "no font loaded");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check that terminal window size and position are sane. */
|
||||
terminal_sanity_check (view);
|
||||
|
||||
term_view = view;
|
||||
|
||||
/* Note: currently there is no API for changing the gfxterm font
|
||||
on the fly, so whatever font the initially loaded theme specifies
|
||||
will be permanent. */
|
||||
grub_gfxterm_set_window (GRUB_VIDEO_RENDER_TARGET_DISPLAY,
|
||||
view->terminal_rect.x,
|
||||
view->terminal_rect.y,
|
||||
view->terminal_rect.width,
|
||||
view->terminal_rect.height,
|
||||
view->double_repaint,
|
||||
terminal_font,
|
||||
view->terminal_border);
|
||||
grub_gfxterm_decorator_hook = grub_gfxmenu_draw_terminal_box;
|
||||
}
|
||||
|
||||
static void
|
||||
init_background (grub_gfxmenu_view_t view)
|
||||
{
|
||||
if (view->scaled_desktop_image || (!view->raw_desktop_image))
|
||||
return;
|
||||
|
||||
struct grub_video_bitmap *scaled_bitmap;
|
||||
if (view->desktop_image_scale_method ==
|
||||
GRUB_VIDEO_BITMAP_SELECTION_METHOD_STRETCH)
|
||||
grub_video_bitmap_create_scaled (&scaled_bitmap,
|
||||
view->screen.width,
|
||||
view->screen.height,
|
||||
view->raw_desktop_image,
|
||||
GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST);
|
||||
else
|
||||
grub_video_bitmap_scale_proportional (&scaled_bitmap,
|
||||
view->screen.width,
|
||||
view->screen.height,
|
||||
view->raw_desktop_image,
|
||||
GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST,
|
||||
view->desktop_image_scale_method,
|
||||
view->desktop_image_v_align,
|
||||
view->desktop_image_h_align);
|
||||
if (! scaled_bitmap)
|
||||
return;
|
||||
view->scaled_desktop_image = scaled_bitmap;
|
||||
|
||||
}
|
||||
|
||||
/* FIXME: previously notifications were displayed in special case.
|
||||
Is it necessary?
|
||||
*/
|
||||
#if 0
|
||||
/* Sets MESSAGE as the progress message for the view.
|
||||
MESSAGE can be 0, in which case no message is displayed. */
|
||||
static void
|
||||
set_progress_message (grub_gfxmenu_view_t view, const char *message)
|
||||
{
|
||||
grub_free (view->progress_message_text);
|
||||
if (message)
|
||||
view->progress_message_text = grub_strdup (message);
|
||||
else
|
||||
view->progress_message_text = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
notify_booting (grub_menu_entry_t entry, void *userdata)
|
||||
{
|
||||
grub_gfxmenu_view_t view = (grub_gfxmenu_view_t) userdata;
|
||||
|
||||
char *s = grub_malloc (100 + grub_strlen (entry->title));
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
grub_sprintf (s, "Booting '%s'", entry->title);
|
||||
set_progress_message (view, s);
|
||||
grub_free (s);
|
||||
grub_gfxmenu_view_redraw (view, &view->progress_message_frame);
|
||||
grub_video_swap_buffers ();
|
||||
if (view->double_repaint)
|
||||
grub_gfxmenu_view_redraw (view, &view->progress_message_frame);
|
||||
}
|
||||
|
||||
static void
|
||||
notify_fallback (grub_menu_entry_t entry, void *userdata)
|
||||
{
|
||||
grub_gfxmenu_view_t view = (grub_gfxmenu_view_t) userdata;
|
||||
|
||||
char *s = grub_malloc (100 + grub_strlen (entry->title));
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
grub_sprintf (s, "Falling back to '%s'", entry->title);
|
||||
set_progress_message (view, s);
|
||||
grub_free (s);
|
||||
grub_gfxmenu_view_redraw (view, &view->progress_message_frame);
|
||||
grub_video_swap_buffers ();
|
||||
if (view->double_repaint)
|
||||
grub_gfxmenu_view_redraw (view, &view->progress_message_frame);
|
||||
}
|
||||
|
||||
static void
|
||||
notify_execution_failure (void *userdata __attribute__ ((unused)))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static struct grub_menu_execute_callback execute_callback =
|
||||
{
|
||||
.notify_booting = notify_booting,
|
||||
.notify_fallback = notify_fallback,
|
||||
.notify_failure = notify_execution_failure
|
||||
};
|
||||
|
||||
#endif
|
@ -964,3 +964,20 @@ void * grub_efi_allocate_iso_buf(grub_uint64_t size)
|
||||
|
||||
return (void *)(unsigned long)address;
|
||||
}
|
||||
|
||||
void * grub_efi_allocate_chain_buf(grub_uint64_t size)
|
||||
{
|
||||
grub_efi_boot_services_t *b;
|
||||
grub_efi_status_t status;
|
||||
grub_efi_physical_address_t address = 0;
|
||||
grub_efi_uintn_t pages = GRUB_EFI_BYTES_TO_PAGES(size);
|
||||
|
||||
b = grub_efi_system_table->boot_services;
|
||||
status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ANY_PAGES, GRUB_EFI_LOADER_DATA, pages, &address);
|
||||
if (status != GRUB_EFI_SUCCESS)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (void *)(unsigned long)address;
|
||||
}
|
||||
|
672
GRUB2/MOD_SRC/grub-2.04/grub-core/kern/efi/mm.c
Normal file
672
GRUB2/MOD_SRC/grub-2.04/grub-core/kern/efi/mm.c
Normal file
@ -0,0 +1,672 @@
|
||||
/* mm.c - generic EFI memory management */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 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/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/efi/api.h>
|
||||
#include <grub/efi/efi.h>
|
||||
#include <grub/cpu/efi/memory.h>
|
||||
|
||||
#if defined (__i386__) || defined (__x86_64__)
|
||||
#include <grub/pci.h>
|
||||
#endif
|
||||
|
||||
#define NEXT_MEMORY_DESCRIPTOR(desc, size) \
|
||||
((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size)))
|
||||
|
||||
#define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12)
|
||||
#define BYTES_TO_PAGES_DOWN(bytes) ((bytes) >> 12)
|
||||
#define PAGES_TO_BYTES(pages) ((pages) << 12)
|
||||
|
||||
/* The size of a memory map obtained from the firmware. This must be
|
||||
a multiplier of 4KB. */
|
||||
#define MEMORY_MAP_SIZE 0x3000
|
||||
|
||||
/* The minimum and maximum heap size for GRUB itself. */
|
||||
#define MIN_HEAP_SIZE 0x100000
|
||||
#define MAX_HEAP_SIZE (1600 * 0x100000)
|
||||
|
||||
static void *finish_mmap_buf = 0;
|
||||
static grub_efi_uintn_t finish_mmap_size = 0;
|
||||
static grub_efi_uintn_t finish_key = 0;
|
||||
static grub_efi_uintn_t finish_desc_size;
|
||||
static grub_efi_uint32_t finish_desc_version;
|
||||
int grub_efi_is_finished = 0;
|
||||
|
||||
/*
|
||||
* We need to roll back EFI allocations on exit. Remember allocations that
|
||||
* we'll free on exit.
|
||||
*/
|
||||
struct efi_allocation;
|
||||
struct efi_allocation {
|
||||
grub_efi_physical_address_t address;
|
||||
grub_efi_uint64_t pages;
|
||||
struct efi_allocation *next;
|
||||
};
|
||||
static struct efi_allocation *efi_allocated_memory;
|
||||
|
||||
static void
|
||||
grub_efi_store_alloc (grub_efi_physical_address_t address,
|
||||
grub_efi_uintn_t pages)
|
||||
{
|
||||
grub_efi_boot_services_t *b;
|
||||
struct efi_allocation *alloc;
|
||||
grub_efi_status_t status;
|
||||
|
||||
b = grub_efi_system_table->boot_services;
|
||||
status = efi_call_3 (b->allocate_pool, GRUB_EFI_LOADER_DATA,
|
||||
sizeof(*alloc), (void**)&alloc);
|
||||
|
||||
if (status == GRUB_EFI_SUCCESS)
|
||||
{
|
||||
alloc->next = efi_allocated_memory;
|
||||
alloc->address = address;
|
||||
alloc->pages = pages;
|
||||
efi_allocated_memory = alloc;
|
||||
}
|
||||
else
|
||||
grub_printf ("Could not malloc memory to remember EFI allocation. "
|
||||
"Exiting GRUB won't free all memory.\n");
|
||||
}
|
||||
|
||||
static void
|
||||
grub_efi_drop_alloc (grub_efi_physical_address_t address,
|
||||
grub_efi_uintn_t pages)
|
||||
{
|
||||
struct efi_allocation *ea, *eap;
|
||||
grub_efi_boot_services_t *b;
|
||||
|
||||
b = grub_efi_system_table->boot_services;
|
||||
|
||||
for (eap = NULL, ea = efi_allocated_memory; ea; eap = ea, ea = ea->next)
|
||||
{
|
||||
if (ea->address != address || ea->pages != pages)
|
||||
continue;
|
||||
|
||||
/* Remove the current entry from the list. */
|
||||
if (eap)
|
||||
eap->next = ea->next;
|
||||
else
|
||||
efi_allocated_memory = ea->next;
|
||||
|
||||
/* Then free the memory backing it. */
|
||||
efi_call_1 (b->free_pool, ea);
|
||||
|
||||
/* And leave, we're done. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate pages. Return the pointer to the first of allocated pages. */
|
||||
void *
|
||||
grub_efi_allocate_pages_real (grub_efi_physical_address_t address,
|
||||
grub_efi_uintn_t pages,
|
||||
grub_efi_allocate_type_t alloctype,
|
||||
grub_efi_memory_type_t memtype)
|
||||
{
|
||||
grub_efi_status_t status;
|
||||
grub_efi_boot_services_t *b;
|
||||
|
||||
/* Limit the memory access to less than 4GB for 32-bit platforms. */
|
||||
if (address > GRUB_EFI_MAX_USABLE_ADDRESS)
|
||||
return 0;
|
||||
|
||||
b = grub_efi_system_table->boot_services;
|
||||
status = efi_call_4 (b->allocate_pages, alloctype, memtype, pages, &address);
|
||||
if (status != GRUB_EFI_SUCCESS)
|
||||
return 0;
|
||||
|
||||
if (address == 0)
|
||||
{
|
||||
/* Uggh, the address 0 was allocated... This is too annoying,
|
||||
so reallocate another one. */
|
||||
address = GRUB_EFI_MAX_USABLE_ADDRESS;
|
||||
status = efi_call_4 (b->allocate_pages, alloctype, memtype, pages, &address);
|
||||
grub_efi_free_pages (0, pages);
|
||||
if (status != GRUB_EFI_SUCCESS)
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_efi_store_alloc (address, pages);
|
||||
|
||||
return (void *) ((grub_addr_t) address);
|
||||
}
|
||||
|
||||
void *
|
||||
grub_efi_allocate_any_pages (grub_efi_uintn_t pages)
|
||||
{
|
||||
return grub_efi_allocate_pages_real (GRUB_EFI_MAX_USABLE_ADDRESS,
|
||||
pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS,
|
||||
GRUB_EFI_LOADER_DATA);
|
||||
}
|
||||
|
||||
void *
|
||||
grub_efi_allocate_fixed (grub_efi_physical_address_t address,
|
||||
grub_efi_uintn_t pages)
|
||||
{
|
||||
return grub_efi_allocate_pages_real (address, pages,
|
||||
GRUB_EFI_ALLOCATE_ADDRESS,
|
||||
GRUB_EFI_LOADER_DATA);
|
||||
}
|
||||
|
||||
/* Free pages starting from ADDRESS. */
|
||||
void
|
||||
grub_efi_free_pages (grub_efi_physical_address_t address,
|
||||
grub_efi_uintn_t pages)
|
||||
{
|
||||
grub_efi_boot_services_t *b;
|
||||
|
||||
b = grub_efi_system_table->boot_services;
|
||||
efi_call_2 (b->free_pages, address, pages);
|
||||
|
||||
grub_efi_drop_alloc (address, pages);
|
||||
}
|
||||
|
||||
#if defined (__i386__) || defined (__x86_64__)
|
||||
|
||||
/* Helper for stop_broadcom. */
|
||||
static int
|
||||
find_card (grub_pci_device_t dev, grub_pci_id_t pciid,
|
||||
void *data __attribute__ ((unused)))
|
||||
{
|
||||
grub_pci_address_t addr;
|
||||
grub_uint8_t cap;
|
||||
grub_uint16_t pm_state;
|
||||
|
||||
if ((pciid & 0xffff) != GRUB_PCI_VENDOR_BROADCOM)
|
||||
return 0;
|
||||
|
||||
addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
|
||||
if (grub_pci_read (addr) >> 24 != GRUB_PCI_CLASS_NETWORK)
|
||||
return 0;
|
||||
cap = grub_pci_find_capability (dev, GRUB_PCI_CAP_POWER_MANAGEMENT);
|
||||
if (!cap)
|
||||
return 0;
|
||||
addr = grub_pci_make_address (dev, cap + 4);
|
||||
pm_state = grub_pci_read_word (addr);
|
||||
pm_state = pm_state | 0x03;
|
||||
grub_pci_write_word (addr, pm_state);
|
||||
grub_pci_read_word (addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
stop_broadcom (void)
|
||||
{
|
||||
grub_pci_iterate (find_card, NULL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
grub_err_t
|
||||
grub_efi_finish_boot_services (grub_efi_uintn_t *outbuf_size, void *outbuf,
|
||||
grub_efi_uintn_t *map_key,
|
||||
grub_efi_uintn_t *efi_desc_size,
|
||||
grub_efi_uint32_t *efi_desc_version)
|
||||
{
|
||||
grub_efi_boot_services_t *b;
|
||||
grub_efi_status_t status;
|
||||
|
||||
#if defined (__i386__) || defined (__x86_64__)
|
||||
const grub_uint16_t apple[] = { 'A', 'p', 'p', 'l', 'e' };
|
||||
int is_apple;
|
||||
|
||||
is_apple = (grub_memcmp (grub_efi_system_table->firmware_vendor,
|
||||
apple, sizeof (apple)) == 0);
|
||||
#endif
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (grub_efi_get_memory_map (&finish_mmap_size, finish_mmap_buf, &finish_key,
|
||||
&finish_desc_size, &finish_desc_version) < 0)
|
||||
return grub_error (GRUB_ERR_IO, "couldn't retrieve memory map");
|
||||
|
||||
if (outbuf && *outbuf_size < finish_mmap_size)
|
||||
return grub_error (GRUB_ERR_IO, "memory map buffer is too small");
|
||||
|
||||
finish_mmap_buf = grub_malloc (finish_mmap_size);
|
||||
if (!finish_mmap_buf)
|
||||
return grub_errno;
|
||||
|
||||
if (grub_efi_get_memory_map (&finish_mmap_size, finish_mmap_buf, &finish_key,
|
||||
&finish_desc_size, &finish_desc_version) <= 0)
|
||||
{
|
||||
grub_free (finish_mmap_buf);
|
||||
return grub_error (GRUB_ERR_IO, "couldn't retrieve memory map");
|
||||
}
|
||||
|
||||
b = grub_efi_system_table->boot_services;
|
||||
status = efi_call_2 (b->exit_boot_services, grub_efi_image_handle,
|
||||
finish_key);
|
||||
if (status == GRUB_EFI_SUCCESS)
|
||||
break;
|
||||
|
||||
if (status != GRUB_EFI_INVALID_PARAMETER)
|
||||
{
|
||||
grub_free (finish_mmap_buf);
|
||||
return grub_error (GRUB_ERR_IO, "couldn't terminate EFI services");
|
||||
}
|
||||
|
||||
grub_free (finish_mmap_buf);
|
||||
grub_printf ("Trying to terminate EFI services again\n");
|
||||
}
|
||||
grub_efi_is_finished = 1;
|
||||
if (outbuf_size)
|
||||
*outbuf_size = finish_mmap_size;
|
||||
if (outbuf)
|
||||
grub_memcpy (outbuf, finish_mmap_buf, finish_mmap_size);
|
||||
if (map_key)
|
||||
*map_key = finish_key;
|
||||
if (efi_desc_size)
|
||||
*efi_desc_size = finish_desc_size;
|
||||
if (efi_desc_version)
|
||||
*efi_desc_version = finish_desc_version;
|
||||
|
||||
#if defined (__i386__) || defined (__x86_64__)
|
||||
if (is_apple)
|
||||
stop_broadcom ();
|
||||
#endif
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* To obtain the UEFI memory map, we must pass a buffer of sufficient size
|
||||
* to hold the entire map. This function returns a sane start value for
|
||||
* buffer size.
|
||||
*/
|
||||
grub_efi_uintn_t
|
||||
grub_efi_find_mmap_size (void)
|
||||
{
|
||||
grub_efi_uintn_t mmap_size = 0;
|
||||
grub_efi_uintn_t desc_size;
|
||||
|
||||
if (grub_efi_get_memory_map (&mmap_size, NULL, NULL, &desc_size, 0) < 0)
|
||||
{
|
||||
grub_error (GRUB_ERR_IO, "cannot get EFI memory map size");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add an extra page, since UEFI can alter the memory map itself on
|
||||
* callbacks or explicit calls, including console output.
|
||||
*/
|
||||
return ALIGN_UP (mmap_size + GRUB_EFI_PAGE_SIZE, GRUB_EFI_PAGE_SIZE);
|
||||
}
|
||||
|
||||
/* Get the memory map as defined in the EFI spec. Return 1 if successful,
|
||||
return 0 if partial, or return -1 if an error occurs. */
|
||||
int
|
||||
grub_efi_get_memory_map (grub_efi_uintn_t *memory_map_size,
|
||||
grub_efi_memory_descriptor_t *memory_map,
|
||||
grub_efi_uintn_t *map_key,
|
||||
grub_efi_uintn_t *descriptor_size,
|
||||
grub_efi_uint32_t *descriptor_version)
|
||||
{
|
||||
grub_efi_status_t status;
|
||||
grub_efi_boot_services_t *b;
|
||||
grub_efi_uintn_t key;
|
||||
grub_efi_uint32_t version;
|
||||
grub_efi_uintn_t size;
|
||||
|
||||
if (grub_efi_is_finished)
|
||||
{
|
||||
int ret = 1;
|
||||
if (*memory_map_size < finish_mmap_size)
|
||||
{
|
||||
grub_memcpy (memory_map, finish_mmap_buf, *memory_map_size);
|
||||
ret = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_memcpy (memory_map, finish_mmap_buf, finish_mmap_size);
|
||||
ret = 1;
|
||||
}
|
||||
*memory_map_size = finish_mmap_size;
|
||||
if (map_key)
|
||||
*map_key = finish_key;
|
||||
if (descriptor_size)
|
||||
*descriptor_size = finish_desc_size;
|
||||
if (descriptor_version)
|
||||
*descriptor_version = finish_desc_version;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Allow some parameters to be missing. */
|
||||
if (! map_key)
|
||||
map_key = &key;
|
||||
if (! descriptor_version)
|
||||
descriptor_version = &version;
|
||||
if (! descriptor_size)
|
||||
descriptor_size = &size;
|
||||
|
||||
b = grub_efi_system_table->boot_services;
|
||||
status = efi_call_5 (b->get_memory_map, memory_map_size, memory_map, map_key,
|
||||
descriptor_size, descriptor_version);
|
||||
if (*descriptor_size == 0)
|
||||
*descriptor_size = sizeof (grub_efi_memory_descriptor_t);
|
||||
if (status == GRUB_EFI_SUCCESS)
|
||||
return 1;
|
||||
else if (status == GRUB_EFI_BUFFER_TOO_SMALL)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Sort the memory map in place. */
|
||||
static void
|
||||
sort_memory_map (grub_efi_memory_descriptor_t *memory_map,
|
||||
grub_efi_uintn_t desc_size,
|
||||
grub_efi_memory_descriptor_t *memory_map_end)
|
||||
{
|
||||
grub_efi_memory_descriptor_t *d1;
|
||||
grub_efi_memory_descriptor_t *d2;
|
||||
|
||||
for (d1 = memory_map;
|
||||
d1 < memory_map_end;
|
||||
d1 = NEXT_MEMORY_DESCRIPTOR (d1, desc_size))
|
||||
{
|
||||
grub_efi_memory_descriptor_t *max_desc = d1;
|
||||
|
||||
for (d2 = NEXT_MEMORY_DESCRIPTOR (d1, desc_size);
|
||||
d2 < memory_map_end;
|
||||
d2 = NEXT_MEMORY_DESCRIPTOR (d2, desc_size))
|
||||
{
|
||||
if (max_desc->num_pages < d2->num_pages)
|
||||
max_desc = d2;
|
||||
}
|
||||
|
||||
if (max_desc != d1)
|
||||
{
|
||||
grub_efi_memory_descriptor_t tmp;
|
||||
|
||||
tmp = *d1;
|
||||
*d1 = *max_desc;
|
||||
*max_desc = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Filter the descriptors. GRUB needs only available memory. */
|
||||
static grub_efi_memory_descriptor_t *
|
||||
filter_memory_map (grub_efi_memory_descriptor_t *memory_map,
|
||||
grub_efi_memory_descriptor_t *filtered_memory_map,
|
||||
grub_efi_uintn_t desc_size,
|
||||
grub_efi_memory_descriptor_t *memory_map_end)
|
||||
{
|
||||
grub_efi_memory_descriptor_t *desc;
|
||||
grub_efi_memory_descriptor_t *filtered_desc;
|
||||
|
||||
for (desc = memory_map, filtered_desc = filtered_memory_map;
|
||||
desc < memory_map_end;
|
||||
desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
|
||||
{
|
||||
if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY
|
||||
#if 1
|
||||
&& desc->physical_start <= GRUB_EFI_MAX_USABLE_ADDRESS
|
||||
#endif
|
||||
&& desc->physical_start + PAGES_TO_BYTES (desc->num_pages) > 0x100000
|
||||
&& desc->num_pages != 0)
|
||||
{
|
||||
grub_memcpy (filtered_desc, desc, desc_size);
|
||||
|
||||
/* Avoid less than 1MB, because some loaders seem to be confused. */
|
||||
if (desc->physical_start < 0x100000)
|
||||
{
|
||||
desc->num_pages -= BYTES_TO_PAGES (0x100000
|
||||
- desc->physical_start);
|
||||
desc->physical_start = 0x100000;
|
||||
}
|
||||
|
||||
#if 1
|
||||
if (BYTES_TO_PAGES (filtered_desc->physical_start)
|
||||
+ filtered_desc->num_pages
|
||||
> BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_USABLE_ADDRESS))
|
||||
filtered_desc->num_pages
|
||||
= (BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_USABLE_ADDRESS)
|
||||
- BYTES_TO_PAGES (filtered_desc->physical_start));
|
||||
#endif
|
||||
|
||||
if (filtered_desc->num_pages == 0)
|
||||
continue;
|
||||
|
||||
filtered_desc = NEXT_MEMORY_DESCRIPTOR (filtered_desc, desc_size);
|
||||
}
|
||||
}
|
||||
|
||||
return filtered_desc;
|
||||
}
|
||||
|
||||
/* Return the total number of pages. */
|
||||
static grub_efi_uint64_t
|
||||
get_total_pages (grub_efi_memory_descriptor_t *memory_map,
|
||||
grub_efi_uintn_t desc_size,
|
||||
grub_efi_memory_descriptor_t *memory_map_end)
|
||||
{
|
||||
grub_efi_memory_descriptor_t *desc;
|
||||
grub_efi_uint64_t total = 0;
|
||||
|
||||
for (desc = memory_map;
|
||||
desc < memory_map_end;
|
||||
desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
|
||||
total += desc->num_pages;
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
/* Add memory regions. */
|
||||
static void
|
||||
add_memory_regions (grub_efi_memory_descriptor_t *memory_map,
|
||||
grub_efi_uintn_t desc_size,
|
||||
grub_efi_memory_descriptor_t *memory_map_end,
|
||||
grub_efi_uint64_t required_pages)
|
||||
{
|
||||
grub_efi_memory_descriptor_t *desc;
|
||||
|
||||
for (desc = memory_map;
|
||||
desc < memory_map_end;
|
||||
desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
|
||||
{
|
||||
grub_efi_uint64_t pages;
|
||||
grub_efi_physical_address_t start;
|
||||
void *addr;
|
||||
|
||||
start = desc->physical_start;
|
||||
pages = desc->num_pages;
|
||||
if (pages > required_pages)
|
||||
{
|
||||
start += PAGES_TO_BYTES (pages - required_pages);
|
||||
pages = required_pages;
|
||||
}
|
||||
|
||||
addr = grub_efi_allocate_pages_real (start, pages,
|
||||
GRUB_EFI_ALLOCATE_ADDRESS,
|
||||
GRUB_EFI_LOADER_CODE);
|
||||
if (! addr)
|
||||
grub_fatal ("cannot allocate conventional memory %p with %u pages",
|
||||
(void *) ((grub_addr_t) start),
|
||||
(unsigned) pages);
|
||||
|
||||
grub_mm_init_region (addr, PAGES_TO_BYTES (pages));
|
||||
|
||||
required_pages -= pages;
|
||||
if (required_pages == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (required_pages > 0)
|
||||
grub_fatal ("too little memory");
|
||||
}
|
||||
|
||||
void
|
||||
grub_efi_memory_fini (void)
|
||||
{
|
||||
/*
|
||||
* Free all stale allocations. grub_efi_free_pages() will remove
|
||||
* the found entry from the list and it will always find the first
|
||||
* list entry (efi_allocated_memory is the list start). Hence we
|
||||
* remove all entries from the list until none is left altogether.
|
||||
*/
|
||||
while (efi_allocated_memory)
|
||||
grub_efi_free_pages (efi_allocated_memory->address,
|
||||
efi_allocated_memory->pages);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Print the memory map. */
|
||||
static void
|
||||
print_memory_map (grub_efi_memory_descriptor_t *memory_map,
|
||||
grub_efi_uintn_t desc_size,
|
||||
grub_efi_memory_descriptor_t *memory_map_end)
|
||||
{
|
||||
grub_efi_memory_descriptor_t *desc;
|
||||
int i;
|
||||
|
||||
for (desc = memory_map, i = 0;
|
||||
desc < memory_map_end;
|
||||
desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size), i++)
|
||||
{
|
||||
grub_printf ("MD: t=%x, p=%llx, v=%llx, n=%llx, a=%llx\n",
|
||||
desc->type, desc->physical_start, desc->virtual_start,
|
||||
desc->num_pages, desc->attribute);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
grub_efi_mm_init (void)
|
||||
{
|
||||
grub_efi_memory_descriptor_t *memory_map;
|
||||
grub_efi_memory_descriptor_t *memory_map_end;
|
||||
grub_efi_memory_descriptor_t *filtered_memory_map;
|
||||
grub_efi_memory_descriptor_t *filtered_memory_map_end;
|
||||
grub_efi_uintn_t map_size;
|
||||
grub_efi_uintn_t desc_size;
|
||||
grub_efi_uint64_t total_pages;
|
||||
grub_efi_uint64_t required_pages;
|
||||
int mm_status;
|
||||
|
||||
/* Prepare a memory region to store two memory maps. */
|
||||
memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE));
|
||||
if (! memory_map)
|
||||
grub_fatal ("cannot allocate memory");
|
||||
|
||||
/* Obtain descriptors for available memory. */
|
||||
map_size = MEMORY_MAP_SIZE;
|
||||
|
||||
mm_status = grub_efi_get_memory_map (&map_size, memory_map, 0, &desc_size, 0);
|
||||
|
||||
if (mm_status == 0)
|
||||
{
|
||||
grub_efi_free_pages
|
||||
((grub_efi_physical_address_t) ((grub_addr_t) memory_map),
|
||||
2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE));
|
||||
|
||||
/* Freeing/allocating operations may increase memory map size. */
|
||||
map_size += desc_size * 32;
|
||||
|
||||
memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (map_size));
|
||||
if (! memory_map)
|
||||
grub_fatal ("cannot allocate memory");
|
||||
|
||||
mm_status = grub_efi_get_memory_map (&map_size, memory_map, 0,
|
||||
&desc_size, 0);
|
||||
}
|
||||
|
||||
if (mm_status < 0)
|
||||
grub_fatal ("cannot get memory map");
|
||||
|
||||
memory_map_end = NEXT_MEMORY_DESCRIPTOR (memory_map, map_size);
|
||||
|
||||
filtered_memory_map = memory_map_end;
|
||||
|
||||
filtered_memory_map_end = filter_memory_map (memory_map, filtered_memory_map,
|
||||
desc_size, memory_map_end);
|
||||
|
||||
/* By default, request a quarter of the available memory. */
|
||||
total_pages = get_total_pages (filtered_memory_map, desc_size,
|
||||
filtered_memory_map_end);
|
||||
|
||||
#if defined (__mips__) && (_MIPS_SIM == _ABI64)
|
||||
required_pages = (total_pages > 4096) ? (total_pages - 4096) : (total_pages >> 1);
|
||||
#else
|
||||
required_pages = (total_pages >> 2);
|
||||
#endif
|
||||
|
||||
if (required_pages < BYTES_TO_PAGES (MIN_HEAP_SIZE))
|
||||
required_pages = BYTES_TO_PAGES (MIN_HEAP_SIZE);
|
||||
else if (required_pages > BYTES_TO_PAGES (MAX_HEAP_SIZE))
|
||||
required_pages = BYTES_TO_PAGES (MAX_HEAP_SIZE);
|
||||
|
||||
/* Sort the filtered descriptors, so that GRUB can allocate pages
|
||||
from smaller regions. */
|
||||
sort_memory_map (filtered_memory_map, desc_size, filtered_memory_map_end);
|
||||
|
||||
/* Allocate memory regions for GRUB's memory management. */
|
||||
add_memory_regions (filtered_memory_map, desc_size,
|
||||
filtered_memory_map_end, required_pages);
|
||||
|
||||
#if 0
|
||||
/* For debug. */
|
||||
map_size = MEMORY_MAP_SIZE;
|
||||
|
||||
if (grub_efi_get_memory_map (&map_size, memory_map, 0, &desc_size, 0) < 0)
|
||||
grub_fatal ("cannot get memory map");
|
||||
|
||||
grub_printf ("printing memory map\n");
|
||||
print_memory_map (memory_map, desc_size,
|
||||
NEXT_MEMORY_DESCRIPTOR (memory_map, map_size));
|
||||
grub_fatal ("Debug. ");
|
||||
#endif
|
||||
|
||||
/* Release the memory maps. */
|
||||
grub_efi_free_pages ((grub_addr_t) memory_map,
|
||||
2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE));
|
||||
}
|
||||
|
||||
#if defined (__aarch64__) || defined (__arm__) || defined (__riscv)
|
||||
grub_err_t
|
||||
grub_efi_get_ram_base(grub_addr_t *base_addr)
|
||||
{
|
||||
grub_efi_memory_descriptor_t *memory_map, *desc;
|
||||
grub_efi_uintn_t memory_map_size, desc_size;
|
||||
int ret;
|
||||
|
||||
memory_map_size = grub_efi_find_mmap_size();
|
||||
|
||||
memory_map = grub_malloc (memory_map_size);
|
||||
if (! memory_map)
|
||||
return GRUB_ERR_OUT_OF_MEMORY;
|
||||
ret = grub_efi_get_memory_map (&memory_map_size, memory_map, NULL,
|
||||
&desc_size, NULL);
|
||||
|
||||
if (ret < 1)
|
||||
return GRUB_ERR_BUG;
|
||||
|
||||
for (desc = memory_map, *base_addr = GRUB_EFI_MAX_USABLE_ADDRESS;
|
||||
(grub_addr_t) desc < ((grub_addr_t) memory_map + memory_map_size);
|
||||
desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
|
||||
if (desc->attribute & GRUB_EFI_MEMORY_WB)
|
||||
*base_addr = grub_min (*base_addr, desc->physical_start);
|
||||
|
||||
grub_free(memory_map);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
#endif
|
@ -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);
|
||||
|
||||
|
23
GRUB2/MOD_SRC/grub-2.04/grub-core/kern/mips64/cache.S
Normal file
23
GRUB2/MOD_SRC/grub-2.04/grub-core/kern/mips64/cache.S
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009,2017 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/symbol.h>
|
||||
|
||||
FUNCTION (grub_arch_sync_caches)
|
||||
jr.hb $ra
|
||||
|
150
GRUB2/MOD_SRC/grub-2.04/grub-core/kern/mips64/dl.c
Normal file
150
GRUB2/MOD_SRC/grub-2.04/grub-core/kern/mips64/dl.c
Normal file
@ -0,0 +1,150 @@
|
||||
/* dl-mips64.c - arch-dependent part of loadable module support */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2002,2005,2007,2009,2017 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/elf.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/cpu/types.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
/* Check if EHDR is a valid ELF header. */
|
||||
grub_err_t
|
||||
grub_arch_dl_check_header (void *ehdr)
|
||||
{
|
||||
Elf_Ehdr *e = ehdr;
|
||||
|
||||
/* Check the magic numbers. */
|
||||
#ifdef GRUB_CPU_WORDS_BIGENDIAN
|
||||
if (e->e_ident[EI_CLASS] != ELFCLASS64
|
||||
|| e->e_ident[EI_DATA] != ELFDATA2MSB
|
||||
|| e->e_machine != EM_MIPS)
|
||||
#else
|
||||
if (e->e_ident[EI_CLASS] != ELFCLASS64
|
||||
|| e->e_ident[EI_DATA] != ELFDATA2LSB
|
||||
|| e->e_machine != EM_MIPS)
|
||||
#endif
|
||||
return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-dependent ELF magic"));
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wcast-align"
|
||||
|
||||
grub_err_t
|
||||
grub_arch_dl_get_tramp_got_size (const void *ehdr __attribute__ ((unused)),
|
||||
grub_size_t *tramp, grub_size_t *got)
|
||||
{
|
||||
*tramp = 0;
|
||||
*got = 0;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
/* Relocate symbols. */
|
||||
grub_err_t
|
||||
grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
|
||||
Elf_Shdr *s, grub_dl_segment_t seg)
|
||||
{
|
||||
Elf_Ehdr *e = ehdr;
|
||||
Elf_Rel *rel, *max;
|
||||
|
||||
for (rel = (Elf_Rel *) ((char *) e + s->sh_offset),
|
||||
max = (Elf_Rel *) ((char *) rel + s->sh_size);
|
||||
rel < max;
|
||||
rel = (Elf_Rel *) ((char *) rel + s->sh_entsize))
|
||||
{
|
||||
grub_uint8_t *addr;
|
||||
Elf_Sym *sym;
|
||||
Elf_Addr r_info;
|
||||
grub_uint64_t sym_value;
|
||||
|
||||
if (seg->size < rel->r_offset)
|
||||
return grub_error (GRUB_ERR_BAD_MODULE,
|
||||
"reloc offset is out of the segment");
|
||||
|
||||
r_info = ((grub_uint64_t) rel->r_info << 32) |
|
||||
(grub_uint32_t) grub_be_to_cpu64 (rel->r_info);
|
||||
|
||||
addr = (grub_uint8_t *) ((char *) seg->addr + rel->r_offset);
|
||||
sym = (Elf_Sym *) ((char *) mod->symtab
|
||||
+ mod->symsize * ELF_R_SYM (r_info));
|
||||
sym_value = sym->st_value;
|
||||
if (s->sh_type == SHT_RELA)
|
||||
{
|
||||
sym_value += ((Elf_Rela *) rel)->r_addend;
|
||||
}
|
||||
switch (ELF_R_TYPE (r_info))
|
||||
{
|
||||
case R_MIPS_64:
|
||||
*(grub_uint64_t *) addr += sym_value;
|
||||
break;
|
||||
case R_MIPS_32:
|
||||
*(grub_uint32_t *) addr += sym_value;
|
||||
break;
|
||||
case R_MIPS_26:
|
||||
{
|
||||
grub_uint32_t value;
|
||||
grub_uint32_t raw;
|
||||
raw = (*(grub_uint32_t *) addr) & 0x3ffffff;
|
||||
value = raw << 2;
|
||||
value += sym_value;
|
||||
raw = (value >> 2) & 0x3ffffff;
|
||||
|
||||
*(grub_uint32_t *) addr =
|
||||
raw | ((*(grub_uint32_t *) addr) & 0xfc000000);
|
||||
}
|
||||
break;
|
||||
case R_MIPS_LO16:
|
||||
#ifdef GRUB_CPU_WORDS_BIGENDIAN
|
||||
addr += 2;
|
||||
#endif
|
||||
*(grub_uint16_t *) addr = (grub_int16_t) sym_value;
|
||||
break;
|
||||
case R_MIPS_HI16:
|
||||
#ifdef GRUB_CPU_WORDS_BIGENDIAN
|
||||
addr += 2;
|
||||
#endif
|
||||
*(grub_uint16_t *) addr = (grub_int16_t) ((sym_value + 0x8000UL) >> 16);
|
||||
break;
|
||||
case R_MIPS_HIGHER:
|
||||
#ifdef GRUB_CPU_WORDS_BIGENDIAN
|
||||
addr += 2;
|
||||
#endif
|
||||
*(grub_uint16_t *) addr = (grub_int16_t) ((sym_value + 0x80008000UL) >> 32);
|
||||
break;
|
||||
case R_MIPS_HIGHEST:
|
||||
#ifdef GRUB_CPU_WORDS_BIGENDIAN
|
||||
addr += 2;
|
||||
#endif
|
||||
*(grub_uint16_t *) addr = (grub_uint16_t) ((sym_value + 0x800080008000UL) >> 48);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
N_("relocation 0x%x is not implemented yet"),
|
||||
ELF_R_TYPE (r_info));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
85
GRUB2/MOD_SRC/grub-2.04/grub-core/kern/mips64/efi/init.c
Normal file
85
GRUB2/MOD_SRC/grub-2.04/grub-core/kern/mips64/efi/init.c
Normal file
@ -0,0 +1,85 @@
|
||||
/* init.c - initialize an arm-based EFI system */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2013 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/kernel.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/cpu/time.h>
|
||||
#include <grub/efi/efi.h>
|
||||
#include <grub/loader.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/machine/loongson.h>
|
||||
|
||||
static grub_uint64_t tmr;
|
||||
static grub_efi_event_t tmr_evt;
|
||||
|
||||
static grub_uint64_t
|
||||
grub_efi_get_time_ms (void)
|
||||
{
|
||||
return tmr;
|
||||
}
|
||||
|
||||
static void
|
||||
grub_loongson_increment_timer (grub_efi_event_t event __attribute__ ((unused)),
|
||||
void *context __attribute__ ((unused)))
|
||||
{
|
||||
tmr += 10;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
grub_machine_init (void)
|
||||
{
|
||||
grub_efi_boot_services_t *b;
|
||||
|
||||
grub_efi_init ();
|
||||
|
||||
b = grub_efi_system_table->boot_services;
|
||||
efi_call_5 (b->create_event, GRUB_EFI_EVT_TIMER | GRUB_EFI_EVT_NOTIFY_SIGNAL,
|
||||
GRUB_EFI_TPL_CALLBACK, grub_loongson_increment_timer, NULL, &tmr_evt);
|
||||
efi_call_3 (b->set_timer, tmr_evt, GRUB_EFI_TIMER_PERIODIC, 100000);
|
||||
|
||||
grub_install_get_time_ms (grub_efi_get_time_ms);
|
||||
|
||||
if (grub_efi_is_loongson ())
|
||||
grub_efi_loongson_init ();
|
||||
else
|
||||
/* FIXME: Get cpuclock from EFI. */
|
||||
grub_timer_init (1000000000U);
|
||||
}
|
||||
|
||||
void
|
||||
grub_machine_fini (int flags)
|
||||
{
|
||||
grub_efi_boot_services_t *b;
|
||||
|
||||
if (!(flags & GRUB_LOADER_FLAG_NORETURN))
|
||||
return;
|
||||
|
||||
b = grub_efi_system_table->boot_services;
|
||||
|
||||
efi_call_3 (b->set_timer, tmr_evt, GRUB_EFI_TIMER_CANCEL, 0);
|
||||
efi_call_1 (b->close_event, tmr_evt);
|
||||
|
||||
if (grub_efi_is_loongson ())
|
||||
grub_efi_loongson_fini ();
|
||||
grub_efi_fini ();
|
||||
}
|
33
GRUB2/MOD_SRC/grub-2.04/grub-core/kern/mips64/efi/loongson.c
Normal file
33
GRUB2/MOD_SRC/grub-2.04/grub-core/kern/mips64/efi/loongson.c
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2017 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/efi/efi.h>
|
||||
#include <grub/cpu/time.h>
|
||||
#include <grub/loader.h>
|
||||
#include <grub/machine/loongson.h>
|
||||
|
||||
void
|
||||
grub_efi_loongson_init (void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
grub_efi_loongson_fini (void)
|
||||
{
|
||||
}
|
||||
|
47
GRUB2/MOD_SRC/grub-2.04/grub-core/kern/mips64/efi/startup.S
Normal file
47
GRUB2/MOD_SRC/grub-2.04/grub-core/kern/mips64/efi/startup.S
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2013 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/symbol.h>
|
||||
|
||||
.file "startup.S"
|
||||
.text
|
||||
|
||||
.set push
|
||||
.align 4
|
||||
|
||||
FUNCTION(_start)
|
||||
/*
|
||||
* EFI_SYSTEM_TABLE and EFI_HANDLE are passed in a1/a0.
|
||||
*/
|
||||
daddiu $sp, -16
|
||||
sd $ra, ($sp)
|
||||
|
||||
dla $a2, grub_efi_image_handle
|
||||
sd $a0, ($a2)
|
||||
dla $a2, grub_efi_system_table
|
||||
sd $a1, ($a2)
|
||||
|
||||
jal grub_main
|
||||
|
||||
1:
|
||||
ld $ra, ($sp)
|
||||
daddiu $sp, 16
|
||||
jr $ra
|
||||
|
||||
.set pop
|
||||
|
47
GRUB2/MOD_SRC/grub-2.04/grub-core/kern/mips64/init.c
Normal file
47
GRUB2/MOD_SRC/grub-2.04/grub-core/kern/mips64/init.c
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009,2017 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/env.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/cpu/mips.h>
|
||||
|
||||
grub_uint32_t grub_arch_cpuclock;
|
||||
|
||||
/* FIXME: use interrupt to count high. */
|
||||
grub_uint64_t
|
||||
grub_get_rtc (void)
|
||||
{
|
||||
static grub_uint32_t high = 0;
|
||||
static grub_uint32_t last = 0;
|
||||
grub_uint32_t low;
|
||||
|
||||
asm volatile ("mfc0 %0, " GRUB_CPU_MIPS_COP0_TIMER_COUNT : "=r" (low));
|
||||
if (low < last)
|
||||
high++;
|
||||
last = low;
|
||||
|
||||
return (((grub_uint64_t) high) << 32) | low;
|
||||
}
|
||||
|
||||
void
|
||||
grub_timer_init (grub_uint32_t cpuclock)
|
||||
{
|
||||
grub_arch_cpuclock = cpuclock;
|
||||
grub_install_get_time_ms (grub_rtc_get_time_ms);
|
||||
}
|
133
GRUB2/MOD_SRC/grub-2.04/grub-core/kern/term.c
Normal file
133
GRUB2/MOD_SRC/grub-2.04/grub-core/kern/term.c
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2002,2003,2005,2007,2008,2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/term.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/time.h>
|
||||
|
||||
struct grub_term_output *grub_term_outputs_disabled;
|
||||
struct grub_term_input *grub_term_inputs_disabled;
|
||||
struct grub_term_output *grub_term_outputs;
|
||||
struct grub_term_input *grub_term_inputs;
|
||||
|
||||
/* Current color state. */
|
||||
grub_uint8_t grub_term_normal_color = GRUB_TERM_DEFAULT_NORMAL_COLOR;
|
||||
grub_uint8_t grub_term_highlight_color = GRUB_TERM_DEFAULT_HIGHLIGHT_COLOR;
|
||||
|
||||
void (*grub_term_poll_usb) (int wait_for_completion) = NULL;
|
||||
void (*grub_net_poll_cards_idle) (void) = NULL;
|
||||
|
||||
/* Put a Unicode character. */
|
||||
static void
|
||||
grub_putcode_dumb (grub_uint32_t code,
|
||||
struct grub_term_output *term)
|
||||
{
|
||||
struct grub_unicode_glyph c =
|
||||
{
|
||||
.base = code,
|
||||
.variant = 0,
|
||||
.attributes = 0,
|
||||
.ncomb = 0,
|
||||
.estimated_width = 1
|
||||
};
|
||||
|
||||
if (code == '\t' && term->getxy)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = GRUB_TERM_TAB_WIDTH - ((term->getxy (term).x)
|
||||
% GRUB_TERM_TAB_WIDTH);
|
||||
while (n--)
|
||||
grub_putcode_dumb (' ', term);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
(term->putchar) (term, &c);
|
||||
if (code == '\n')
|
||||
grub_putcode_dumb ('\r', term);
|
||||
}
|
||||
|
||||
static void
|
||||
grub_xputs_dumb (const char *str)
|
||||
{
|
||||
for (; *str; str++)
|
||||
{
|
||||
grub_term_output_t term;
|
||||
grub_uint32_t code = *str;
|
||||
if (code > 0x7f)
|
||||
code = '?';
|
||||
|
||||
FOR_ACTIVE_TERM_OUTPUTS(term)
|
||||
grub_putcode_dumb (code, term);
|
||||
}
|
||||
}
|
||||
|
||||
void (*grub_xputs) (const char *str) = grub_xputs_dumb;
|
||||
|
||||
int (*grub_key_remap)(int key) = NULL;
|
||||
int
|
||||
grub_getkey_noblock (void)
|
||||
{
|
||||
grub_term_input_t term;
|
||||
|
||||
if (grub_term_poll_usb)
|
||||
grub_term_poll_usb (0);
|
||||
|
||||
if (grub_net_poll_cards_idle)
|
||||
grub_net_poll_cards_idle ();
|
||||
|
||||
FOR_ACTIVE_TERM_INPUTS(term)
|
||||
{
|
||||
int key = term->getkey (term);
|
||||
if (grub_key_remap)
|
||||
key = grub_key_remap(key);
|
||||
if (key != GRUB_TERM_NO_KEY)
|
||||
return key;
|
||||
}
|
||||
|
||||
return GRUB_TERM_NO_KEY;
|
||||
}
|
||||
|
||||
int
|
||||
grub_getkey (void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
grub_refresh ();
|
||||
|
||||
while (1)
|
||||
{
|
||||
ret = grub_getkey_noblock ();
|
||||
if (ret != GRUB_TERM_NO_KEY)
|
||||
return ret;
|
||||
grub_cpu_idle ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
grub_refresh (void)
|
||||
{
|
||||
struct grub_term_output *term;
|
||||
|
||||
FOR_ACTIVE_TERM_OUTPUTS(term)
|
||||
grub_term_refresh (term);
|
||||
}
|
40
GRUB2/MOD_SRC/grub-2.04/grub-core/lib/efi/halt.c
Normal file
40
GRUB2/MOD_SRC/grub-2.04/grub-core/lib/efi/halt.c
Normal file
@ -0,0 +1,40 @@
|
||||
/* efi.c - generic EFI support */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2006,2007,2008,2009,2010 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/efi/api.h>
|
||||
#include <grub/efi/efi.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/kernel.h>
|
||||
#include <grub/acpi.h>
|
||||
#include <grub/loader.h>
|
||||
|
||||
void
|
||||
grub_halt (void)
|
||||
{
|
||||
grub_machine_fini (GRUB_LOADER_FLAG_NORETURN);
|
||||
#if !defined(__ia64__) && !defined(__arm__) && !defined(__aarch64__) && !defined(__mips__) &&\
|
||||
!defined(__riscv)
|
||||
grub_acpi_halt ();
|
||||
#endif
|
||||
efi_call_4 (grub_efi_system_table->runtime_services->reset_system,
|
||||
GRUB_EFI_RESET_SHUTDOWN, GRUB_EFI_SUCCESS, 0, NULL);
|
||||
|
||||
while (1);
|
||||
}
|
495
GRUB2/MOD_SRC/grub-2.04/grub-core/lib/mips64/efi/loongson.c
Normal file
495
GRUB2/MOD_SRC/grub-2.04/grub-core/lib/mips64/efi/loongson.c
Normal file
@ -0,0 +1,495 @@
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2017 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/cache.h>
|
||||
#include <grub/efi/efi.h>
|
||||
#include <grub/cpu/efi/memory.h>
|
||||
#include <grub/cpu/memory.h>
|
||||
#include <grub/machine/loongson.h>
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
|
||||
#define loongson_params (&loongson_boot_params->boot_params.efi.smbios.lp)
|
||||
#define loongson_boot_params_size ALIGN_UP (sizeof (*loongson_boot_params), 8)
|
||||
#define loongson_reset_code_size (&grub_efi_loongson_reset_end - &grub_efi_loongson_reset_start)
|
||||
|
||||
extern grub_uint8_t grub_efi_loongson_reset_start;
|
||||
extern grub_uint8_t grub_efi_loongson_reset_end;
|
||||
|
||||
static struct
|
||||
{
|
||||
grub_efi_loongson_boot_params boot_params;
|
||||
grub_efi_loongson_memory_map memory_map;
|
||||
grub_efi_loongson_cpu_info cpu_info;
|
||||
grub_efi_loongson_system_info system_info;
|
||||
grub_efi_loongson_irq_src_routing_table irq_src_routing_table;
|
||||
grub_efi_loongson_interface_info interface_info;
|
||||
grub_efi_loongson_special_attribute special_attribute;
|
||||
grub_efi_loongson_board_devices board_devices;
|
||||
} GRUB_PACKED
|
||||
* loongson_boot_params;
|
||||
|
||||
static void
|
||||
grub_efi_loongson_init_reset_system (void)
|
||||
{
|
||||
grub_efi_loongson_boot_params *boot_params;
|
||||
grub_uint8_t *reset_code_addr = (grub_uint8_t *) loongson_boot_params +
|
||||
loongson_boot_params_size;
|
||||
|
||||
boot_params = &loongson_boot_params->boot_params;
|
||||
grub_efi_loongson_reset_system_addr =
|
||||
(grub_uint64_t) grub_efi_system_table->runtime_services->reset_system;
|
||||
grub_memcpy (reset_code_addr, &grub_efi_loongson_reset_start, loongson_reset_code_size);
|
||||
grub_arch_sync_caches (reset_code_addr, loongson_reset_code_size);
|
||||
|
||||
boot_params->reset_system.reset_cold = (grub_uint64_t) reset_code_addr +
|
||||
((grub_uint64_t) &grub_efi_loongson_reset_cold -
|
||||
(grub_uint64_t) &grub_efi_loongson_reset_start);
|
||||
boot_params->reset_system.reset_warm = (grub_uint64_t) reset_code_addr +
|
||||
((grub_uint64_t) &grub_efi_loongson_reset_warm -
|
||||
(grub_uint64_t) &grub_efi_loongson_reset_start);
|
||||
boot_params->reset_system.shutdown = (grub_uint64_t) reset_code_addr +
|
||||
((grub_uint64_t) &grub_efi_loongson_reset_shutdown -
|
||||
(grub_uint64_t) &grub_efi_loongson_reset_start);
|
||||
boot_params->reset_system.do_suspend = (grub_uint64_t) reset_code_addr +
|
||||
((grub_uint64_t) &grub_efi_loongson_reset_suspend -
|
||||
(grub_uint64_t) &grub_efi_loongson_reset_start);
|
||||
}
|
||||
|
||||
static void
|
||||
grub_efi_loongson_init_smbios (grub_efi_loongson_smbios_table *smbios_table)
|
||||
{
|
||||
grub_efi_loongson_smbios_table *dst = &loongson_boot_params->boot_params.efi.smbios;
|
||||
|
||||
dst->vers = smbios_table->vers;
|
||||
dst->vga_bios = smbios_table->vga_bios;
|
||||
}
|
||||
|
||||
static void
|
||||
grub_efi_loongson_init_cpu_info (grub_efi_loongson_smbios_table *smbios_table)
|
||||
{
|
||||
grub_efi_loongson_cpu_info *src = (void *) smbios_table->lp.cpu_offset;
|
||||
grub_efi_loongson_cpu_info *dst = &loongson_boot_params->cpu_info;
|
||||
|
||||
if (!src)
|
||||
return;
|
||||
|
||||
grub_memcpy (dst, src, sizeof (grub_efi_loongson_cpu_info));
|
||||
loongson_params->cpu_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params;
|
||||
}
|
||||
|
||||
static void
|
||||
grub_efi_loongson_init_system_info (grub_efi_loongson_smbios_table *smbios_table)
|
||||
{
|
||||
grub_efi_loongson_system_info *src = (void *) smbios_table->lp.system_offset;
|
||||
grub_efi_loongson_system_info *dst = &loongson_boot_params->system_info;
|
||||
|
||||
if (!src)
|
||||
return;
|
||||
|
||||
grub_memcpy (dst, src, sizeof (grub_efi_loongson_system_info));
|
||||
loongson_params->system_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params;
|
||||
}
|
||||
|
||||
static void
|
||||
grub_efi_loongson_init_irq_src_routing_table (grub_efi_loongson_smbios_table *smbios_table)
|
||||
{
|
||||
grub_efi_loongson_irq_src_routing_table *src = (void *) smbios_table->lp.irq_offset;
|
||||
grub_efi_loongson_irq_src_routing_table *dst = &loongson_boot_params->irq_src_routing_table;
|
||||
|
||||
if (!src)
|
||||
return;
|
||||
|
||||
grub_memcpy (dst, src, sizeof (grub_efi_loongson_irq_src_routing_table));
|
||||
loongson_params->irq_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params;
|
||||
}
|
||||
|
||||
static void
|
||||
grub_efi_loongson_init_interface_info (grub_efi_loongson_smbios_table *smbios_table)
|
||||
{
|
||||
grub_efi_loongson_interface_info *src = (void *) smbios_table->lp.interface_offset;
|
||||
grub_efi_loongson_interface_info *dst = &loongson_boot_params->interface_info;
|
||||
|
||||
if (!src)
|
||||
return;
|
||||
|
||||
grub_memcpy (dst, src, sizeof (grub_efi_loongson_interface_info));
|
||||
loongson_params->interface_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params;
|
||||
}
|
||||
|
||||
static void
|
||||
grub_efi_loongson_init_special_attribute (grub_efi_loongson_smbios_table *smbios_table)
|
||||
{
|
||||
grub_efi_loongson_special_attribute *src = (void *) smbios_table->lp.special_offset;
|
||||
grub_efi_loongson_special_attribute *dst = &loongson_boot_params->special_attribute;
|
||||
|
||||
if (!src)
|
||||
return;
|
||||
|
||||
grub_memcpy (dst, src, sizeof (grub_efi_loongson_special_attribute));
|
||||
loongson_params->special_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params;
|
||||
}
|
||||
|
||||
static void
|
||||
grub_efi_loongson_init_board_devices (grub_efi_loongson_smbios_table *smbios_table)
|
||||
{
|
||||
grub_efi_loongson_board_devices *src = (void *) smbios_table->lp.boarddev_table_offset;
|
||||
grub_efi_loongson_board_devices *dst = &loongson_boot_params->board_devices;
|
||||
|
||||
if (!src)
|
||||
return;
|
||||
|
||||
grub_memcpy (dst, src, sizeof (grub_efi_loongson_board_devices));
|
||||
loongson_params->boarddev_table_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params;
|
||||
}
|
||||
|
||||
#define ADD_MEMORY_DESCRIPTOR(desc, size) \
|
||||
((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size)))
|
||||
|
||||
static void
|
||||
grub_efi_loongson_init_memory_map (grub_efi_loongson_smbios_table *smbios_table,
|
||||
grub_efi_memory_descriptor_t *mmap_buf,
|
||||
grub_efi_uintn_t mmap_size,
|
||||
grub_efi_uintn_t desc_size)
|
||||
{
|
||||
grub_efi_loongson_memory_map *src = (void *) smbios_table->lp.memory_offset;
|
||||
grub_efi_loongson_memory_map *dst = &loongson_boot_params->memory_map;
|
||||
grub_efi_memory_descriptor_t *mmap_end;
|
||||
grub_efi_memory_descriptor_t *desc;
|
||||
grub_efi_memory_descriptor_t *desc_next;
|
||||
grub_efi_uint32_t mem_types_reserved[] =
|
||||
{
|
||||
1, // GRUB_EFI_RESERVED_MEMORY_TYPE
|
||||
0, // GRUB_EFI_LOADER_CODE
|
||||
0, // GRUB_EFI_LOADER_DATA
|
||||
0, // GRUB_EFI_BOOT_SERVICES_CODE
|
||||
0, // GRUB_EFI_BOOT_SERVICES_DATA
|
||||
1, // GRUB_EFI_RUNTIME_SERVICES_CODE
|
||||
1, // GRUB_EFI_RUNTIME_SERVICES_DATA
|
||||
0, // GRUB_EFI_CONVENTIONAL_MEMORY
|
||||
1, // GRUB_EFI_UNUSABLE_MEMORY
|
||||
0, // GRUB_EFI_ACPI_RECLAIM_MEMORY
|
||||
0, // GRUB_EFI_ACPI_MEMORY_NVS
|
||||
1, // GRUB_EFI_MEMORY_MAPPED_IO
|
||||
1, // GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE
|
||||
1, // GRUB_EFI_PAL_CODE
|
||||
1, // GRUB_EFI_PERSISTENT_MEMORY
|
||||
};
|
||||
grub_uint32_t need_sort = 1;
|
||||
|
||||
if (!src)
|
||||
return;
|
||||
|
||||
dst->vers = src->vers;
|
||||
dst->nr_map = 0;
|
||||
dst->mem_freq = src->mem_freq;
|
||||
loongson_params->memory_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params;
|
||||
|
||||
if (!mmap_buf || !mmap_size || !desc_size)
|
||||
return;
|
||||
|
||||
mmap_end = ADD_MEMORY_DESCRIPTOR (mmap_buf, mmap_size);
|
||||
|
||||
/* drop reserved */
|
||||
for (desc = mmap_buf,
|
||||
desc_next = desc;
|
||||
desc < mmap_end;
|
||||
desc = ADD_MEMORY_DESCRIPTOR (desc, desc_size))
|
||||
{
|
||||
desc->type = mem_types_reserved[desc->type];
|
||||
if (desc->type)
|
||||
continue;
|
||||
|
||||
if (desc != desc_next)
|
||||
*desc_next = *desc;
|
||||
desc_next = ADD_MEMORY_DESCRIPTOR (desc_next, desc_size);
|
||||
}
|
||||
mmap_end = desc_next;
|
||||
|
||||
/* sort: low->high */
|
||||
while (need_sort)
|
||||
{
|
||||
need_sort = 0;
|
||||
|
||||
for (desc = mmap_buf,
|
||||
desc_next = ADD_MEMORY_DESCRIPTOR (desc, desc_size);
|
||||
(desc < mmap_end) && (desc_next < mmap_end);
|
||||
desc = desc_next,
|
||||
desc_next = ADD_MEMORY_DESCRIPTOR (desc, desc_size))
|
||||
{
|
||||
grub_efi_memory_descriptor_t tmp;
|
||||
|
||||
if (desc->physical_start <= desc_next->physical_start)
|
||||
continue;
|
||||
|
||||
tmp = *desc;
|
||||
*desc = *desc_next;
|
||||
*desc_next = tmp;
|
||||
need_sort = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* combine continuous memory map */
|
||||
for (desc = mmap_buf,
|
||||
desc_next = ADD_MEMORY_DESCRIPTOR (desc, desc_size);
|
||||
desc_next < mmap_end;
|
||||
desc_next = ADD_MEMORY_DESCRIPTOR (desc_next, desc_size))
|
||||
{
|
||||
grub_efi_physical_address_t prev_end = desc->physical_start + (desc->num_pages << 12);
|
||||
|
||||
if (prev_end == desc_next->physical_start)
|
||||
{
|
||||
desc->num_pages += desc_next->num_pages;
|
||||
continue;
|
||||
}
|
||||
|
||||
desc = ADD_MEMORY_DESCRIPTOR (desc, desc_size);
|
||||
grub_memcpy (desc, desc_next, desc_size);
|
||||
}
|
||||
mmap_end = ADD_MEMORY_DESCRIPTOR (desc, desc_size);
|
||||
|
||||
/* write to loongson memory map */
|
||||
for (desc = mmap_buf;
|
||||
desc < mmap_end;
|
||||
desc = ADD_MEMORY_DESCRIPTOR (desc, desc_size))
|
||||
{
|
||||
grub_efi_physical_address_t physical_start = grub_vtop ((void *) desc->physical_start);
|
||||
grub_efi_physical_address_t physical_end = physical_start + (desc->num_pages << 12);
|
||||
|
||||
physical_start = ALIGN_UP (physical_start, 0x100000);
|
||||
physical_end = ALIGN_DOWN (physical_end, 0x100000);
|
||||
|
||||
if (physical_start >= physical_end || (physical_end - physical_start) < 0x100000)
|
||||
continue;
|
||||
|
||||
dst->map[dst->nr_map].node_id = (desc->physical_start >> 44) & 0xf;
|
||||
dst->map[dst->nr_map].mem_type = (physical_end <= 0x10000000) ?
|
||||
GRUB_EFI_LOONGSON_SYSTEM_RAM_LOW :
|
||||
GRUB_EFI_LOONGSON_SYSTEM_RAM_HIGH;
|
||||
dst->map[dst->nr_map].mem_start = physical_start;
|
||||
dst->map[dst->nr_map].mem_size = (physical_end - physical_start) >> 20;
|
||||
|
||||
grub_dprintf ("loongson", "memory map %03u: 0x%016lx 0x%016lx @ %u\n",
|
||||
dst->nr_map, physical_start, physical_end - physical_start,
|
||||
dst->map[dst->nr_map].node_id);
|
||||
|
||||
dst->nr_map ++;
|
||||
}
|
||||
}
|
||||
|
||||
#define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12)
|
||||
#define SUB_MEMORY_DESCRIPTOR(desc, size) \
|
||||
((grub_efi_memory_descriptor_t *) ((char *) (desc) - (size)))
|
||||
|
||||
void
|
||||
grub_efi_loongson_alloc_boot_params (void)
|
||||
{
|
||||
grub_efi_memory_descriptor_t *mmap_buf;
|
||||
grub_efi_memory_descriptor_t *mmap_end;
|
||||
grub_efi_memory_descriptor_t *desc;
|
||||
grub_efi_uintn_t mmap_size;
|
||||
grub_efi_uintn_t desc_size;
|
||||
grub_efi_physical_address_t address;
|
||||
grub_efi_allocate_type_t type;
|
||||
grub_efi_uintn_t pages;
|
||||
grub_efi_status_t status;
|
||||
grub_efi_boot_services_t *b;
|
||||
int mm_status;
|
||||
|
||||
type = GRUB_EFI_ALLOCATE_ADDRESS;
|
||||
pages = BYTES_TO_PAGES (loongson_boot_params_size + loongson_reset_code_size);
|
||||
|
||||
mmap_size = (1 << 12);
|
||||
mmap_buf = grub_malloc (mmap_size);
|
||||
if (!mmap_buf)
|
||||
grub_fatal ("out of memory!");
|
||||
|
||||
mm_status = grub_efi_get_memory_map (&mmap_size, mmap_buf, 0, &desc_size, 0);
|
||||
if (mm_status == 0)
|
||||
{
|
||||
grub_free (mmap_buf);
|
||||
mmap_size += desc_size * 32;
|
||||
|
||||
mmap_buf = grub_malloc (mmap_size);
|
||||
if (!mmap_buf)
|
||||
grub_fatal ("out of memory!");
|
||||
|
||||
mm_status = grub_efi_get_memory_map (&mmap_size, mmap_buf, 0, &desc_size, 0);
|
||||
}
|
||||
|
||||
if (mm_status < 0)
|
||||
grub_fatal ("cannot get memory map!");
|
||||
|
||||
mmap_end = ADD_MEMORY_DESCRIPTOR (mmap_buf, mmap_size);
|
||||
|
||||
for (desc = SUB_MEMORY_DESCRIPTOR (mmap_end, desc_size);
|
||||
desc >= mmap_buf;
|
||||
desc = SUB_MEMORY_DESCRIPTOR (desc, desc_size))
|
||||
{
|
||||
if (desc->type != GRUB_EFI_CONVENTIONAL_MEMORY)
|
||||
continue;
|
||||
if (desc->physical_start >= GRUB_EFI_MAX_USABLE_ADDRESS)
|
||||
continue;
|
||||
if (desc->num_pages < pages)
|
||||
continue;
|
||||
|
||||
address = desc->physical_start;
|
||||
break;
|
||||
}
|
||||
|
||||
grub_free (mmap_buf);
|
||||
|
||||
b = grub_efi_system_table->boot_services;
|
||||
status = efi_call_4 (b->allocate_pages, type, GRUB_EFI_RUNTIME_SERVICES_DATA, pages, &address);
|
||||
if (status != GRUB_EFI_SUCCESS)
|
||||
grub_fatal ("cannot allocate Loongson boot parameters!");
|
||||
|
||||
loongson_boot_params = (void *) ((grub_addr_t) address);
|
||||
}
|
||||
|
||||
void
|
||||
grub_efi_loongson_free_boot_params (void)
|
||||
{
|
||||
grub_efi_free_pages ((grub_addr_t) loongson_boot_params,
|
||||
BYTES_TO_PAGES (loongson_boot_params_size + loongson_reset_code_size));
|
||||
}
|
||||
|
||||
void *
|
||||
grub_efi_loongson_get_smbios_table (void)
|
||||
{
|
||||
static grub_efi_loongson_smbios_table *smbios_table;
|
||||
grub_efi_loongson_boot_params *old_boot_params;
|
||||
struct bootparamsinterface* boot_params;
|
||||
void * tmp_boot_params = NULL;
|
||||
char * p = NULL;
|
||||
if(smbios_table)
|
||||
return smbios_table;
|
||||
|
||||
tmp_boot_params = grub_efi_loongson_get_boot_params();
|
||||
if(tmp_boot_params == NULL)
|
||||
{
|
||||
grub_dprintf("loongson", "tmp_boot_params is NULL\n");
|
||||
return tmp_boot_params;
|
||||
}
|
||||
|
||||
boot_params = (struct bootparamsinterface *)tmp_boot_params;
|
||||
p = (char *)&(boot_params->signature);
|
||||
if(grub_strncmp(p, "BPI", 3) == 0)
|
||||
{
|
||||
grub_dprintf("loongson", "find new bpi\n");
|
||||
return boot_params ? boot_params : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
old_boot_params = (grub_efi_loongson_boot_params *)tmp_boot_params;
|
||||
return old_boot_params ? &old_boot_params->efi.smbios : 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
grub_efi_is_loongson (void)
|
||||
{
|
||||
return grub_efi_loongson_get_smbios_table () ? 1 : 0;
|
||||
}
|
||||
|
||||
void *
|
||||
grub_efi_loongson_get_boot_params (void)
|
||||
{
|
||||
static void * boot_params = NULL;
|
||||
grub_efi_configuration_table_t *tables;
|
||||
grub_efi_guid_t smbios_guid = GRUB_EFI_LOONGSON_SMBIOS_TABLE_GUID;
|
||||
unsigned int i;
|
||||
|
||||
if (boot_params)
|
||||
return boot_params;
|
||||
|
||||
/* Look for Loongson SMBIOS in UEFI config tables. */
|
||||
tables = grub_efi_system_table->configuration_table;
|
||||
|
||||
for (i = 0; i < grub_efi_system_table->num_table_entries; i++)
|
||||
if (grub_memcmp (&tables[i].vendor_guid, &smbios_guid, sizeof (smbios_guid)) == 0)
|
||||
{
|
||||
boot_params= tables[i].vendor_table;
|
||||
grub_dprintf ("loongson", "found registered SMBIOS @ %p\n", boot_params);
|
||||
break;
|
||||
}
|
||||
return boot_params;
|
||||
}
|
||||
|
||||
grub_uint8_t
|
||||
grub_efi_loongson_calculatesum8 (const grub_uint8_t *buffer, grub_efi_uintn_t length)
|
||||
{
|
||||
grub_uint8_t sum;
|
||||
grub_efi_uintn_t count;
|
||||
|
||||
for (sum = 0, count = 0; count < length; count++)
|
||||
{
|
||||
sum = (grub_uint8_t) (sum + *(buffer + count));
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
grub_uint8_t
|
||||
grub_efi_loongson_grub_calculatechecksum8 (const grub_uint8_t *buffer, grub_efi_uintn_t length)
|
||||
{
|
||||
grub_uint8_t checksum;
|
||||
|
||||
checksum = grub_efi_loongson_calculatesum8(buffer, length);
|
||||
|
||||
return (grub_uint8_t) (0x100 - checksum);
|
||||
}
|
||||
|
||||
|
||||
grub_uint32_t
|
||||
grub_efi_loongson_memmap_sort(struct memmap array[], grub_uint32_t length, mem_map * bpmem, grub_uint32_t index, grub_uint32_t memtype)
|
||||
{
|
||||
grub_uint64_t tempmemsize = 0;
|
||||
grub_uint32_t j = 0;
|
||||
grub_uint32_t t = 0;
|
||||
|
||||
for(j = 0; j < length;)
|
||||
{
|
||||
tempmemsize = array[j].memsize;
|
||||
for(t = j + 1; t < length; t++)
|
||||
{
|
||||
if(array[j].memstart + tempmemsize == array[t].memstart)
|
||||
{
|
||||
tempmemsize += array[t].memsize;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
bpmem->map[index].memtype = memtype;
|
||||
bpmem->map[index].memstart = array[j].memstart;
|
||||
bpmem->map[index].memsize = tempmemsize;
|
||||
grub_dprintf("loongson", "map[%d]:type %x, start 0x%llx, end 0x%llx\n",
|
||||
index,
|
||||
bpmem->map[index].memtype,
|
||||
(unsigned long long)bpmem->map[index].memstart,
|
||||
(unsigned long long)bpmem->map[index].memstart+ bpmem->map[index].memsize
|
||||
);
|
||||
j = t;
|
||||
index++;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2017 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/symbol.h>
|
||||
|
||||
.file "loongson.S"
|
||||
.text
|
||||
|
||||
.set push
|
||||
.set noreorder
|
||||
.align 4
|
||||
|
||||
VARIABLE (grub_efi_loongson_reset_start)
|
||||
|
||||
VARIABLE (grub_efi_loongson_reset_system_addr)
|
||||
.dword 0
|
||||
|
||||
reset_system:
|
||||
bal 1f
|
||||
move $a1, $zero
|
||||
1:
|
||||
ld $t9, -16($ra)
|
||||
move $a2, $zero
|
||||
jalr $t9
|
||||
move $a3, $zero
|
||||
|
||||
FUNCTION(grub_efi_loongson_reset_cold)
|
||||
b reset_system
|
||||
li $a0, 0
|
||||
|
||||
FUNCTION(grub_efi_loongson_reset_warm)
|
||||
b reset_system
|
||||
li $a0, 1
|
||||
|
||||
FUNCTION(grub_efi_loongson_reset_shutdown)
|
||||
b reset_system
|
||||
li $a0, 2
|
||||
|
||||
FUNCTION(grub_efi_loongson_reset_suspend)
|
||||
b reset_system
|
||||
li $a0, 3
|
||||
|
||||
VARIABLE (grub_efi_loongson_reset_end)
|
||||
|
||||
.set pop
|
||||
|
169
GRUB2/MOD_SRC/grub-2.04/grub-core/lib/mips64/relocator.c
Normal file
169
GRUB2/MOD_SRC/grub-2.04/grub-core/lib/mips64/relocator.c
Normal file
@ -0,0 +1,169 @@
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2017 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/types.h>
|
||||
#include <grub/types.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/cache.h>
|
||||
|
||||
#include <grub/mips64/relocator.h>
|
||||
#include <grub/relocator_private.h>
|
||||
|
||||
extern grub_uint8_t grub_relocator_forward_start;
|
||||
extern grub_uint8_t grub_relocator_forward_end;
|
||||
extern grub_uint8_t grub_relocator_backward_start;
|
||||
extern grub_uint8_t grub_relocator_backward_end;
|
||||
|
||||
#define REGW_SIZEOF (6 * sizeof (grub_uint32_t))
|
||||
#define JUMP_SIZEOF (2 * sizeof (grub_uint32_t))
|
||||
|
||||
#define RELOCATOR_SRC_SIZEOF(x) (&grub_relocator_##x##_end \
|
||||
- &grub_relocator_##x##_start)
|
||||
#define RELOCATOR_SIZEOF(x) (RELOCATOR_SRC_SIZEOF(x) \
|
||||
+ REGW_SIZEOF * 3)
|
||||
grub_size_t grub_relocator_align = sizeof (grub_uint64_t);
|
||||
grub_size_t grub_relocator_forward_size;
|
||||
grub_size_t grub_relocator_backward_size;
|
||||
grub_size_t grub_relocator_jumper_size = JUMP_SIZEOF + REGW_SIZEOF;
|
||||
|
||||
void
|
||||
grub_cpu_relocator_init (void)
|
||||
{
|
||||
grub_relocator_forward_size = RELOCATOR_SIZEOF(forward);
|
||||
grub_relocator_backward_size = RELOCATOR_SIZEOF(backward);
|
||||
}
|
||||
|
||||
static void
|
||||
write_reg (int regn, grub_uint64_t val, void **target)
|
||||
{
|
||||
grub_uint32_t lui;
|
||||
grub_uint32_t ori;
|
||||
grub_uint32_t dsll;
|
||||
|
||||
/* lui $r, 0 */
|
||||
lui = (0x3c00 | regn) << 16;
|
||||
/* ori $r, $r, 0 */
|
||||
ori = (0x3400 | (regn << 5) | regn) << 16;
|
||||
/* dsll $r, $r, 16 */
|
||||
dsll = (regn << 16) | (regn << 11) | (16 << 6) | 56;
|
||||
|
||||
/* lui $r, val[63:48]. */
|
||||
*(grub_uint32_t *) *target = lui | (grub_uint16_t) (val >> 48);
|
||||
*target = ((grub_uint32_t *) *target) + 1;
|
||||
/* ori $r, val[47:32]. */
|
||||
*(grub_uint32_t *) *target = ori | (grub_uint16_t) (val >> 32);
|
||||
*target = ((grub_uint32_t *) *target) + 1;
|
||||
/* dsll $r, $r, 16 */
|
||||
*(grub_uint32_t *) *target = dsll;
|
||||
*target = ((grub_uint32_t *) *target) + 1;
|
||||
/* ori $r, val[31:16]. */
|
||||
*(grub_uint32_t *) *target = ori | (grub_uint16_t) (val >> 16);
|
||||
*target = ((grub_uint32_t *) *target) + 1;
|
||||
/* dsll $r, $r, 16 */
|
||||
*(grub_uint32_t *) *target = dsll;
|
||||
*target = ((grub_uint32_t *) *target) + 1;
|
||||
/* ori $r, val[15:0]. */
|
||||
*(grub_uint32_t *) *target = ori | (grub_uint16_t) val;
|
||||
*target = ((grub_uint32_t *) *target) + 1;
|
||||
}
|
||||
|
||||
static void
|
||||
write_jump (int regn, void **target)
|
||||
{
|
||||
/* j $r. */
|
||||
*(grub_uint32_t *) *target = (regn << 21) | 0x8;
|
||||
*target = ((grub_uint32_t *) *target) + 1;
|
||||
/* nop. */
|
||||
*(grub_uint32_t *) *target = 0;
|
||||
*target = ((grub_uint32_t *) *target) + 1;
|
||||
}
|
||||
|
||||
void
|
||||
grub_cpu_relocator_jumper (void *rels, grub_addr_t addr)
|
||||
{
|
||||
write_reg (1, addr, &rels);
|
||||
write_jump (1, &rels);
|
||||
}
|
||||
|
||||
void
|
||||
grub_cpu_relocator_backward (void *ptr0, void *src, void *dest,
|
||||
grub_size_t size)
|
||||
{
|
||||
void *ptr = ptr0;
|
||||
write_reg (8, (grub_uint64_t) src, &ptr);
|
||||
write_reg (9, (grub_uint64_t) dest, &ptr);
|
||||
write_reg (10, (grub_uint64_t) size, &ptr);
|
||||
grub_memcpy (ptr, &grub_relocator_backward_start,
|
||||
RELOCATOR_SRC_SIZEOF (backward));
|
||||
}
|
||||
|
||||
void
|
||||
grub_cpu_relocator_forward (void *ptr0, void *src, void *dest,
|
||||
grub_size_t size)
|
||||
{
|
||||
void *ptr = ptr0;
|
||||
write_reg (8, (grub_uint64_t) src, &ptr);
|
||||
write_reg (9, (grub_uint64_t) dest, &ptr);
|
||||
write_reg (10, (grub_uint64_t) size, &ptr);
|
||||
grub_memcpy (ptr, &grub_relocator_forward_start,
|
||||
RELOCATOR_SRC_SIZEOF (forward));
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_relocator64_boot (struct grub_relocator *rel,
|
||||
struct grub_relocator64_state state)
|
||||
{
|
||||
grub_relocator_chunk_t ch;
|
||||
void *ptr;
|
||||
grub_err_t err;
|
||||
void *relst;
|
||||
grub_size_t relsize;
|
||||
grub_size_t stateset_size = 31 * REGW_SIZEOF + JUMP_SIZEOF;
|
||||
unsigned i;
|
||||
grub_addr_t vtarget;
|
||||
|
||||
err = grub_relocator_alloc_chunk_align (rel, &ch, 0,
|
||||
(0xffffffff - stateset_size)
|
||||
+ 1, stateset_size,
|
||||
grub_relocator_align,
|
||||
GRUB_RELOCATOR_PREFERENCE_NONE, 0);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ptr = get_virtual_current_address (ch);
|
||||
for (i = 1; i < 32; i++)
|
||||
write_reg (i, state.gpr[i], &ptr);
|
||||
write_jump (state.jumpreg, &ptr);
|
||||
|
||||
vtarget = (grub_addr_t) grub_map_memory (get_physical_target_address (ch),
|
||||
stateset_size);
|
||||
|
||||
err = grub_relocator_prepare_relocs (rel, vtarget, &relst, &relsize);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
grub_arch_sync_caches ((void *) relst, relsize);
|
||||
|
||||
((void (*) (void)) relst) ();
|
||||
|
||||
/* Not reached. */
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
56
GRUB2/MOD_SRC/grub-2.04/grub-core/lib/mips64/relocator_asm.S
Normal file
56
GRUB2/MOD_SRC/grub-2.04/grub-core/lib/mips64/relocator_asm.S
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2017 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/symbol.h>
|
||||
|
||||
.p2align 4 /* force 16-byte alignment */
|
||||
|
||||
.set push
|
||||
.set noreorder
|
||||
.set nomacro
|
||||
|
||||
VARIABLE (grub_relocator_forward_start)
|
||||
|
||||
copycont1:
|
||||
ld $11,0($8)
|
||||
sd $11,0($9)
|
||||
daddiu $8, $8, 8
|
||||
daddiu $10, $10, -8
|
||||
bne $10, $0, copycont1
|
||||
daddiu $9, $9, 8
|
||||
|
||||
VARIABLE (grub_relocator_forward_end)
|
||||
|
||||
VARIABLE (grub_relocator_backward_start)
|
||||
|
||||
daddu $9, $9, $10
|
||||
daddu $8, $8, $10
|
||||
/* Backward movsl is implicitly off-by-one. compensate that. */
|
||||
daddiu $9, $9, -8
|
||||
daddiu $8, $8, -8
|
||||
copycont2:
|
||||
ld $11,0($8)
|
||||
sd $11,0($9)
|
||||
daddiu $8, $8, -8
|
||||
daddiu $10, $10, -8
|
||||
bne $10, $0, copycont2
|
||||
daddiu $9, $9, -8
|
||||
|
||||
VARIABLE (grub_relocator_backward_end)
|
||||
|
||||
.set pop
|
69
GRUB2/MOD_SRC/grub-2.04/grub-core/lib/mips64/setjmp.S
Normal file
69
GRUB2/MOD_SRC/grub-2.04/grub-core/lib/mips64/setjmp.S
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2003,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/symbol.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/mips64/asm.h>
|
||||
|
||||
.file "setjmp.S"
|
||||
|
||||
GRUB_MOD_LICENSE "GPLv3+"
|
||||
|
||||
.text
|
||||
|
||||
/*
|
||||
* int grub_setjmp (grub_jmp_buf env)
|
||||
*/
|
||||
FUNCTION(grub_setjmp)
|
||||
GRUB_ASM_REG_S $s0, 0($a0)
|
||||
GRUB_ASM_REG_S $s1, 8($a0)
|
||||
GRUB_ASM_REG_S $s2, 16($a0)
|
||||
GRUB_ASM_REG_S $s3, 24($a0)
|
||||
GRUB_ASM_REG_S $s4, 32($a0)
|
||||
GRUB_ASM_REG_S $s5, 40($a0)
|
||||
GRUB_ASM_REG_S $s6, 48($a0)
|
||||
GRUB_ASM_REG_S $s7, 56($a0)
|
||||
GRUB_ASM_REG_S $s8, 64($a0)
|
||||
GRUB_ASM_REG_S $gp, 72($a0)
|
||||
GRUB_ASM_REG_S $sp, 80($a0)
|
||||
GRUB_ASM_REG_S $ra, 88($a0)
|
||||
move $v0, $zero
|
||||
move $v1, $zero
|
||||
jr $ra
|
||||
nop
|
||||
/*
|
||||
* int grub_longjmp (grub_jmp_buf env, int val)
|
||||
*/
|
||||
FUNCTION(grub_longjmp)
|
||||
GRUB_ASM_REG_L $s0, 0($a0)
|
||||
GRUB_ASM_REG_L $s1, 8($a0)
|
||||
GRUB_ASM_REG_L $s2, 16($a0)
|
||||
GRUB_ASM_REG_L $s3, 24($a0)
|
||||
GRUB_ASM_REG_L $s4, 32($a0)
|
||||
GRUB_ASM_REG_L $s5, 40($a0)
|
||||
GRUB_ASM_REG_L $s6, 48($a0)
|
||||
GRUB_ASM_REG_L $s7, 56($a0)
|
||||
GRUB_ASM_REG_L $s8, 64($a0)
|
||||
GRUB_ASM_REG_L $gp, 72($a0)
|
||||
GRUB_ASM_REG_L $sp, 80($a0)
|
||||
GRUB_ASM_REG_L $ra, 88($a0)
|
||||
addiu $v0, $zero, 1
|
||||
movn $v0, $a1, $a1
|
||||
move $v1, $zero
|
||||
jr $ra
|
||||
nop
|
1660
GRUB2/MOD_SRC/grub-2.04/grub-core/lib/relocator.c
Normal file
1660
GRUB2/MOD_SRC/grub-2.04/grub-core/lib/relocator.c
Normal file
File diff suppressed because it is too large
Load Diff
26
GRUB2/MOD_SRC/grub-2.04/grub-core/lib/setjmp.S
Normal file
26
GRUB2/MOD_SRC/grub-2.04/grub-core/lib/setjmp.S
Normal file
@ -0,0 +1,26 @@
|
||||
#if defined(__i386__)
|
||||
#include "./i386/setjmp.S"
|
||||
#elif defined(__x86_64__)
|
||||
#include "./x86_64/setjmp.S"
|
||||
#elif defined(__sparc__)
|
||||
#include "./sparc64/setjmp.S"
|
||||
#elif defined(__mips__)
|
||||
#if _MIPS_SIM == _ABI64
|
||||
#include "./mips64/setjmp.S"
|
||||
#else
|
||||
#include "./mips/setjmp.S"
|
||||
#endif
|
||||
#elif defined(__powerpc__) || defined(__PPC__)
|
||||
#include "./powerpc/setjmp.S"
|
||||
#elif defined(__ia64__)
|
||||
#include "./ia64/setjmp.S"
|
||||
#include "./ia64/longjmp.S"
|
||||
#elif defined(__arm__)
|
||||
#include "./arm/setjmp.S"
|
||||
#elif defined(__aarch64__)
|
||||
#include "./arm64/setjmp.S"
|
||||
#elif defined(__riscv)
|
||||
#include "./riscv/setjmp.S"
|
||||
#else
|
||||
#error "Unknown target cpu type"
|
||||
#endif
|
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
852
GRUB2/MOD_SRC/grub-2.04/grub-core/loader/arm64/linux.c
Normal file
852
GRUB2/MOD_SRC/grub-2.04/grub-core/loader/arm64/linux.c
Normal file
@ -0,0 +1,852 @@
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2013 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/charset.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/fdt.h>
|
||||
#include <grub/linux.h>
|
||||
#include <grub/loader.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/types.h>
|
||||
#include <grub/cpu/linux.h>
|
||||
#include <grub/efi/efi.h>
|
||||
#include <grub/efi/fdtload.h>
|
||||
#include <grub/efi/memory.h>
|
||||
#include <grub/efi/pe32.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/lib/cmdline.h>
|
||||
#include <grub/verify.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/env.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static grub_dl_t my_mod;
|
||||
static int loaded;
|
||||
|
||||
static void *kernel_addr;
|
||||
static grub_uint64_t kernel_size;
|
||||
|
||||
static char *linux_args;
|
||||
static grub_uint32_t cmdline_size;
|
||||
|
||||
static grub_addr_t initrd_start;
|
||||
static grub_addr_t initrd_end;
|
||||
|
||||
#define LINUX_MAX_ARGC 1024
|
||||
static int ventoy_debug = 0;
|
||||
static int ventoy_initrd_called = 0;
|
||||
static int ventoy_linux_argc = 0;
|
||||
static char **ventoy_linux_args = NULL;
|
||||
static int ventoy_extra_initrd_num = 0;
|
||||
static char *ventoy_extra_initrd_list[256];
|
||||
static grub_err_t
|
||||
grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[]);
|
||||
|
||||
grub_err_t
|
||||
grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh)
|
||||
{
|
||||
if (lh->magic != GRUB_LINUX_ARMXX_MAGIC_SIGNATURE)
|
||||
return grub_error(GRUB_ERR_BAD_OS, "invalid magic number");
|
||||
|
||||
if ((lh->code0 & 0xffff) != GRUB_PE32_MAGIC)
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
N_("plain image kernel not supported - rebuild with CONFIG_(U)EFI_STUB enabled"));
|
||||
|
||||
grub_dprintf ("linux", "UEFI stub kernel:\n");
|
||||
grub_dprintf ("linux", "PE/COFF header @ %08x\n", lh->hdr_offset);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
finalize_params_linux (void)
|
||||
{
|
||||
int node, retval;
|
||||
|
||||
void *fdt;
|
||||
|
||||
fdt = grub_fdt_load (GRUB_EFI_LINUX_FDT_EXTRA_SPACE);
|
||||
|
||||
if (!fdt)
|
||||
goto failure;
|
||||
|
||||
node = grub_fdt_find_subnode (fdt, 0, "chosen");
|
||||
if (node < 0)
|
||||
node = grub_fdt_add_subnode (fdt, 0, "chosen");
|
||||
|
||||
if (node < 1)
|
||||
goto failure;
|
||||
|
||||
/* Set initrd info */
|
||||
if (initrd_start && initrd_end > initrd_start)
|
||||
{
|
||||
grub_dprintf ("linux", "Initrd @ %p-%p\n",
|
||||
(void *) initrd_start, (void *) initrd_end);
|
||||
|
||||
retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-start",
|
||||
initrd_start);
|
||||
if (retval)
|
||||
goto failure;
|
||||
retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-end",
|
||||
initrd_end);
|
||||
if (retval)
|
||||
goto failure;
|
||||
}
|
||||
|
||||
if (grub_fdt_install() != GRUB_ERR_NONE)
|
||||
goto failure;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
failure:
|
||||
grub_fdt_unload();
|
||||
return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT");
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_arch_efi_linux_boot_image (grub_addr_t addr, grub_size_t size, char *args)
|
||||
{
|
||||
grub_efi_memory_mapped_device_path_t *mempath;
|
||||
grub_efi_handle_t image_handle;
|
||||
grub_efi_boot_services_t *b;
|
||||
grub_efi_status_t status;
|
||||
grub_efi_loaded_image_t *loaded_image;
|
||||
int len;
|
||||
|
||||
mempath = grub_malloc (2 * sizeof (grub_efi_memory_mapped_device_path_t));
|
||||
if (!mempath)
|
||||
return grub_errno;
|
||||
|
||||
mempath[0].header.type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE;
|
||||
mempath[0].header.subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE;
|
||||
mempath[0].header.length = grub_cpu_to_le16_compile_time (sizeof (*mempath));
|
||||
mempath[0].memory_type = GRUB_EFI_LOADER_DATA;
|
||||
mempath[0].start_address = addr;
|
||||
mempath[0].end_address = addr + size;
|
||||
|
||||
mempath[1].header.type = GRUB_EFI_END_DEVICE_PATH_TYPE;
|
||||
mempath[1].header.subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
|
||||
mempath[1].header.length = sizeof (grub_efi_device_path_t);
|
||||
|
||||
b = grub_efi_system_table->boot_services;
|
||||
status = b->load_image (0, grub_efi_image_handle,
|
||||
(grub_efi_device_path_t *) mempath,
|
||||
(void *) addr, size, &image_handle);
|
||||
if (status != GRUB_EFI_SUCCESS)
|
||||
return grub_error (GRUB_ERR_BAD_OS, "cannot load image");
|
||||
|
||||
grub_dprintf ("linux", "linux command line: '%s'\n", args);
|
||||
|
||||
/* Convert command line to UCS-2 */
|
||||
loaded_image = grub_efi_get_loaded_image (image_handle);
|
||||
loaded_image->load_options_size = len =
|
||||
(grub_strlen (args) + 1) * sizeof (grub_efi_char16_t);
|
||||
loaded_image->load_options =
|
||||
grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
|
||||
if (!loaded_image->load_options)
|
||||
return grub_errno;
|
||||
|
||||
loaded_image->load_options_size =
|
||||
2 * grub_utf8_to_utf16 (loaded_image->load_options, len,
|
||||
(grub_uint8_t *) args, len, NULL);
|
||||
|
||||
grub_dprintf ("linux", "starting image %p\n", image_handle);
|
||||
status = b->start_image (image_handle, 0, NULL);
|
||||
|
||||
/* When successful, not reached */
|
||||
b->unload_image (image_handle);
|
||||
grub_efi_free_pages ((grub_addr_t) loaded_image->load_options,
|
||||
GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
|
||||
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
|
||||
static void ventoy_debug_pause(void)
|
||||
{
|
||||
char key;
|
||||
|
||||
if (0 == ventoy_debug)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
grub_printf("press Enter to continue ......\n");
|
||||
while (1)
|
||||
{
|
||||
key = grub_getkey();
|
||||
if (key == '\n' || key == '\r')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int ventoy_preboot(void)
|
||||
{
|
||||
int i;
|
||||
const char *file;
|
||||
char buf[128];
|
||||
|
||||
if (ventoy_debug)
|
||||
{
|
||||
grub_printf("ventoy_preboot %d %d\n", ventoy_linux_argc, ventoy_initrd_called);
|
||||
ventoy_debug_pause();
|
||||
}
|
||||
|
||||
if (ventoy_linux_argc == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ventoy_initrd_called)
|
||||
{
|
||||
ventoy_initrd_called = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_snprintf(buf, sizeof(buf), "mem:%s:size:%s", grub_env_get("ventoy_cpio_addr"), grub_env_get("ventoy_cpio_size"));
|
||||
|
||||
ventoy_extra_initrd_list[ventoy_extra_initrd_num++] = grub_strdup(buf);
|
||||
|
||||
file = grub_env_get("vtoy_img_part_file");
|
||||
if (file)
|
||||
{
|
||||
ventoy_extra_initrd_list[ventoy_extra_initrd_num++] = grub_strdup(file);
|
||||
}
|
||||
|
||||
if (ventoy_debug)
|
||||
{
|
||||
grub_printf("========== initrd list ==========\n");
|
||||
for (i = 0; i < ventoy_extra_initrd_num; i++)
|
||||
{
|
||||
grub_printf("%s\n", ventoy_extra_initrd_list[i]);
|
||||
}
|
||||
grub_printf("=================================\n");
|
||||
|
||||
ventoy_debug_pause();
|
||||
}
|
||||
|
||||
grub_cmd_initrd(NULL, ventoy_extra_initrd_num, ventoy_extra_initrd_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ventoy_boot_opt_filter(char *opt)
|
||||
{
|
||||
if (grub_strcmp(opt, "noinitrd") == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (grub_strcmp(opt, "vga=current") == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (grub_strncmp(opt, "rdinit=", 7) == 0)
|
||||
{
|
||||
if (grub_strcmp(opt, "rdinit=/vtoy/vtoy") != 0)
|
||||
{
|
||||
opt[0] = 'v';
|
||||
opt[1] = 't';
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (grub_strncmp(opt, "init=", 5) == 0)
|
||||
{
|
||||
opt[0] = 'v';
|
||||
opt[1] = 't';
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ventoy_debug)
|
||||
{
|
||||
if (grub_strcmp(opt, "quiet") == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (grub_strncmp(opt, "loglevel=", 9) == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (grub_strcmp(opt, "splash") == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ventoy_bootopt_hook(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
int TmpIdx;
|
||||
int count = 0;
|
||||
const char *env;
|
||||
char c;
|
||||
char *newenv;
|
||||
char *last, *pos;
|
||||
|
||||
//grub_printf("ventoy_bootopt_hook: %d %d\n", argc, ventoy_linux_argc);
|
||||
|
||||
if (ventoy_linux_argc == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* To avoid --- parameter, we split two parts */
|
||||
for (TmpIdx = 0; TmpIdx < argc; TmpIdx++)
|
||||
{
|
||||
if (ventoy_boot_opt_filter(argv[TmpIdx]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strncmp(argv[TmpIdx], "--", 2) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ventoy_linux_args[count++] = grub_strdup(argv[TmpIdx]);
|
||||
}
|
||||
|
||||
for (i = 0; i < ventoy_linux_argc; i++)
|
||||
{
|
||||
ventoy_linux_args[count] = ventoy_linux_args[i + (LINUX_MAX_ARGC / 2)];
|
||||
ventoy_linux_args[i + (LINUX_MAX_ARGC / 2)] = NULL;
|
||||
|
||||
if (ventoy_linux_args[count][0] == '@')
|
||||
{
|
||||
env = grub_env_get(ventoy_linux_args[count] + 1);
|
||||
if (env)
|
||||
{
|
||||
grub_free(ventoy_linux_args[count]);
|
||||
|
||||
newenv = grub_strdup(env);
|
||||
last = newenv;
|
||||
|
||||
while (*last)
|
||||
{
|
||||
while (*last)
|
||||
{
|
||||
if (*last != ' ' && *last != '\t')
|
||||
{
|
||||
break;
|
||||
}
|
||||
last++;
|
||||
}
|
||||
|
||||
if (*last == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
for (pos = last; *pos; pos++)
|
||||
{
|
||||
if (*pos == ' ' || *pos == '\t')
|
||||
{
|
||||
c = *pos;
|
||||
*pos = 0;
|
||||
if (0 == ventoy_boot_opt_filter(last))
|
||||
{
|
||||
ventoy_linux_args[count++] = grub_strdup(last);
|
||||
}
|
||||
*pos = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (*pos == 0)
|
||||
{
|
||||
if (0 == ventoy_boot_opt_filter(last))
|
||||
{
|
||||
ventoy_linux_args[count++] = grub_strdup(last);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
last = pos + 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
while (TmpIdx < argc)
|
||||
{
|
||||
if (ventoy_boot_opt_filter(argv[TmpIdx]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ventoy_linux_args[count++] = grub_strdup(argv[TmpIdx]);
|
||||
TmpIdx++;
|
||||
}
|
||||
|
||||
if (ventoy_debug)
|
||||
{
|
||||
ventoy_linux_args[count++] = grub_strdup("loglevel=7");
|
||||
}
|
||||
|
||||
ventoy_linux_argc = count;
|
||||
|
||||
if (ventoy_debug)
|
||||
{
|
||||
grub_printf("========== bootoption ==========\n");
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
grub_printf("%s ", ventoy_linux_args[i]);
|
||||
}
|
||||
grub_printf("\n================================\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_set_boot_opt (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
const char *vtdebug;
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
ventoy_linux_args[ventoy_linux_argc + (LINUX_MAX_ARGC / 2) ] = grub_strdup(argv[i]);
|
||||
ventoy_linux_argc++;
|
||||
}
|
||||
|
||||
vtdebug = grub_env_get("vtdebug_flag");
|
||||
if (vtdebug && vtdebug[0])
|
||||
{
|
||||
ventoy_debug = 1;
|
||||
}
|
||||
|
||||
if (ventoy_debug) grub_printf("ventoy set boot opt %d\n", ventoy_linux_argc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_unset_boot_opt (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
for (i = 0; i < LINUX_MAX_ARGC; i++)
|
||||
{
|
||||
if (ventoy_linux_args[i])
|
||||
{
|
||||
grub_free(ventoy_linux_args[i]);
|
||||
}
|
||||
}
|
||||
|
||||
ventoy_debug = 0;
|
||||
ventoy_linux_argc = 0;
|
||||
ventoy_initrd_called = 0;
|
||||
grub_memset(ventoy_linux_args, 0, sizeof(char *) * LINUX_MAX_ARGC);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_extra_initrd_append (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
int newclen = 0;
|
||||
char *pos = NULL;
|
||||
char *end = NULL;
|
||||
char buf[256] = {0};
|
||||
|
||||
if (argc != 1)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (pos = argv[0]; *pos; pos++)
|
||||
{
|
||||
if (*pos == '/')
|
||||
{
|
||||
end = pos;
|
||||
}
|
||||
}
|
||||
|
||||
if (end)
|
||||
{
|
||||
/* grub2 newc bug workaround */
|
||||
newclen = (int)grub_strlen(end + 1);
|
||||
if ((110 + newclen) % 4 == 0)
|
||||
{
|
||||
grub_snprintf(buf, sizeof(buf), "newc:.%s:%s", end + 1, argv[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_snprintf(buf, sizeof(buf), "newc:%s:%s", end + 1, argv[0]);
|
||||
}
|
||||
|
||||
if (ventoy_extra_initrd_num < 256)
|
||||
{
|
||||
ventoy_extra_initrd_list[ventoy_extra_initrd_num++] = grub_strdup(buf);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_extra_initrd_reset (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
for (i = 0; i < ventoy_extra_initrd_num; i++)
|
||||
{
|
||||
if (ventoy_extra_initrd_list[i])
|
||||
{
|
||||
grub_free(ventoy_extra_initrd_list[i]);
|
||||
}
|
||||
}
|
||||
|
||||
grub_memset(ventoy_extra_initrd_list, 0, sizeof(ventoy_extra_initrd_list));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static grub_err_t
|
||||
grub_linux_boot (void)
|
||||
{
|
||||
ventoy_preboot();
|
||||
|
||||
if (finalize_params_linux () != GRUB_ERR_NONE)
|
||||
return grub_errno;
|
||||
|
||||
return (grub_arch_efi_linux_boot_image((grub_addr_t)kernel_addr,
|
||||
kernel_size, linux_args));
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_linux_unload (void)
|
||||
{
|
||||
grub_dl_unref (my_mod);
|
||||
loaded = 0;
|
||||
if (initrd_start)
|
||||
grub_efi_free_pages ((grub_efi_physical_address_t) initrd_start,
|
||||
GRUB_EFI_BYTES_TO_PAGES (initrd_end - initrd_start));
|
||||
initrd_start = initrd_end = 0;
|
||||
grub_free (linux_args);
|
||||
if (kernel_addr)
|
||||
grub_efi_free_pages ((grub_addr_t) kernel_addr,
|
||||
GRUB_EFI_BYTES_TO_PAGES (kernel_size));
|
||||
grub_fdt_unload ();
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* As per linux/Documentation/arm/Booting
|
||||
* ARM initrd needs to be covered by kernel linear mapping,
|
||||
* so place it in the first 512MB of DRAM.
|
||||
*
|
||||
* As per linux/Documentation/arm64/booting.txt
|
||||
* ARM64 initrd needs to be contained entirely within a 1GB aligned window
|
||||
* of up to 32GB of size that covers the kernel image as well.
|
||||
* Since the EFI stub loader will attempt to load the kernel near start of
|
||||
* RAM, place the buffer in the first 32GB of RAM.
|
||||
*/
|
||||
#ifdef __arm__
|
||||
#define INITRD_MAX_ADDRESS_OFFSET (512U * 1024 * 1024)
|
||||
#else /* __aarch64__ */
|
||||
#define INITRD_MAX_ADDRESS_OFFSET (32ULL * 1024 * 1024 * 1024)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This function returns a pointer to a legally allocated initrd buffer,
|
||||
* or NULL if unsuccessful
|
||||
*/
|
||||
static void *
|
||||
allocate_initrd_mem (int initrd_pages)
|
||||
{
|
||||
grub_addr_t max_addr;
|
||||
|
||||
if (grub_efi_get_ram_base (&max_addr) != GRUB_ERR_NONE)
|
||||
return NULL;
|
||||
|
||||
max_addr += INITRD_MAX_ADDRESS_OFFSET - 1;
|
||||
|
||||
return grub_efi_allocate_pages_real (max_addr, initrd_pages,
|
||||
GRUB_EFI_ALLOCATE_MAX_ADDRESS,
|
||||
GRUB_EFI_LOADER_DATA);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 };
|
||||
int initrd_size, initrd_pages;
|
||||
void *initrd_mem = NULL;
|
||||
|
||||
if (argc == 0)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!loaded)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
N_("you need to load the kernel first"));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (grub_initrd_init (argc, argv, &initrd_ctx))
|
||||
goto fail;
|
||||
|
||||
initrd_size = grub_get_initrd_size (&initrd_ctx);
|
||||
grub_dprintf ("linux", "Loading initrd\n");
|
||||
|
||||
initrd_pages = (GRUB_EFI_BYTES_TO_PAGES (initrd_size));
|
||||
initrd_mem = allocate_initrd_mem (initrd_pages);
|
||||
|
||||
if (!initrd_mem)
|
||||
{
|
||||
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (grub_initrd_load (&initrd_ctx, argv, initrd_mem))
|
||||
goto fail;
|
||||
|
||||
initrd_start = (grub_addr_t) initrd_mem;
|
||||
initrd_end = initrd_start + initrd_size;
|
||||
grub_dprintf ("linux", "[addr=%p, size=0x%x]\n",
|
||||
(void *) initrd_start, initrd_size);
|
||||
|
||||
fail:
|
||||
grub_initrd_close (&initrd_ctx);
|
||||
if (initrd_mem && !initrd_start)
|
||||
grub_efi_free_pages ((grub_addr_t) initrd_mem, initrd_pages);
|
||||
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
grub_file_t file = 0;
|
||||
struct linux_arch_kernel_header lh;
|
||||
grub_err_t err;
|
||||
|
||||
grub_dl_ref (my_mod);
|
||||
|
||||
if (argc == 0)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
file = grub_file_open (argv[0], GRUB_FILE_TYPE_LINUX_KERNEL);
|
||||
if (!file)
|
||||
goto fail;
|
||||
|
||||
kernel_size = grub_file_size (file);
|
||||
|
||||
if (grub_file_read (file, &lh, sizeof (lh)) < (long) sizeof (lh))
|
||||
return grub_errno;
|
||||
|
||||
if (grub_arch_efi_linux_check_image (&lh) != GRUB_ERR_NONE)
|
||||
goto fail;
|
||||
|
||||
grub_loader_unset();
|
||||
|
||||
grub_dprintf ("linux", "kernel file size: %lld\n", (long long) kernel_size);
|
||||
kernel_addr = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (kernel_size));
|
||||
grub_dprintf ("linux", "kernel numpages: %lld\n",
|
||||
(long long) GRUB_EFI_BYTES_TO_PAGES (kernel_size));
|
||||
if (!kernel_addr)
|
||||
{
|
||||
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
grub_file_seek (file, 0);
|
||||
if (grub_file_read (file, kernel_addr, kernel_size)
|
||||
< (grub_int64_t) kernel_size)
|
||||
{
|
||||
if (!grub_errno)
|
||||
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
grub_dprintf ("linux", "kernel @ %p\n", kernel_addr);
|
||||
|
||||
cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE);
|
||||
linux_args = grub_malloc (cmdline_size);
|
||||
if (!linux_args)
|
||||
{
|
||||
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
|
||||
goto fail;
|
||||
}
|
||||
grub_memcpy (linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE));
|
||||
|
||||
if (ventoy_linux_argc)
|
||||
{
|
||||
ventoy_bootopt_hook(argc, argv);
|
||||
err = grub_create_loader_cmdline (ventoy_linux_argc, ventoy_linux_args,
|
||||
linux_args + sizeof (LINUX_IMAGE) - 1,
|
||||
cmdline_size,
|
||||
GRUB_VERIFY_KERNEL_CMDLINE); }
|
||||
else
|
||||
{
|
||||
err = grub_create_loader_cmdline (argc, argv,
|
||||
linux_args + sizeof (LINUX_IMAGE) - 1,
|
||||
cmdline_size,
|
||||
GRUB_VERIFY_KERNEL_CMDLINE);
|
||||
}
|
||||
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
if (grub_errno == GRUB_ERR_NONE)
|
||||
{
|
||||
grub_loader_set (grub_linux_boot, grub_linux_unload, 0);
|
||||
loaded = 1;
|
||||
}
|
||||
|
||||
fail:
|
||||
if (file)
|
||||
grub_file_close (file);
|
||||
|
||||
if (grub_errno != GRUB_ERR_NONE)
|
||||
{
|
||||
grub_dl_unref (my_mod);
|
||||
loaded = 0;
|
||||
}
|
||||
|
||||
if (linux_args && !loaded)
|
||||
grub_free (linux_args);
|
||||
|
||||
if (kernel_addr && !loaded)
|
||||
grub_efi_free_pages ((grub_addr_t) kernel_addr,
|
||||
GRUB_EFI_BYTES_TO_PAGES (kernel_size));
|
||||
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
ventoy_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
const char *file;
|
||||
char buf[64];
|
||||
|
||||
if (ventoy_debug) grub_printf("ventoy_cmd_initrd %d\n", ventoy_linux_argc);
|
||||
|
||||
if (ventoy_linux_argc == 0)
|
||||
{
|
||||
return grub_cmd_initrd(cmd, argc, argv);
|
||||
}
|
||||
|
||||
grub_snprintf(buf, sizeof(buf), "mem:%s:size:%s", grub_env_get("ventoy_cpio_addr"), grub_env_get("ventoy_cpio_size"));
|
||||
|
||||
if (ventoy_debug) grub_printf("membuf=%s\n", buf);
|
||||
|
||||
ventoy_extra_initrd_list[ventoy_extra_initrd_num++] = grub_strdup(buf);
|
||||
|
||||
file = grub_env_get("vtoy_img_part_file");
|
||||
if (file)
|
||||
{
|
||||
ventoy_extra_initrd_list[ventoy_extra_initrd_num++] = grub_strdup(file);
|
||||
}
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
ventoy_extra_initrd_list[ventoy_extra_initrd_num++] = grub_strdup(argv[i]);
|
||||
}
|
||||
|
||||
ventoy_initrd_called = 1;
|
||||
|
||||
if (ventoy_debug)
|
||||
{
|
||||
grub_printf("========== initrd list ==========\n");
|
||||
for (i = 0; i < ventoy_extra_initrd_num; i++)
|
||||
{
|
||||
grub_printf("%s\n", ventoy_extra_initrd_list[i]);
|
||||
}
|
||||
grub_printf("=================================\n");
|
||||
}
|
||||
|
||||
return grub_cmd_initrd(cmd, ventoy_extra_initrd_num, ventoy_extra_initrd_list);
|
||||
}
|
||||
|
||||
|
||||
static grub_command_t cmd_linux, cmd_initrd, cmd_linuxefi, cmd_initrdefi;
|
||||
static grub_command_t cmd_set_bootopt, cmd_unset_bootopt, cmd_extra_initrd_append, cmd_extra_initrd_reset;
|
||||
|
||||
|
||||
GRUB_MOD_INIT (linux)
|
||||
{
|
||||
cmd_linux = grub_register_command ("linux", grub_cmd_linux, 0,
|
||||
N_("Load Linux."));
|
||||
cmd_initrd = grub_register_command ("initrd", ventoy_cmd_initrd, 0,
|
||||
N_("Load initrd."));
|
||||
|
||||
cmd_linuxefi = grub_register_command ("linuxefi", grub_cmd_linux,
|
||||
0, N_("Load Linux."));
|
||||
cmd_initrdefi = grub_register_command ("initrdefi", ventoy_cmd_initrd,
|
||||
0, N_("Load initrd."));
|
||||
|
||||
cmd_set_bootopt = grub_register_command ("vt_set_boot_opt", grub_cmd_set_boot_opt, 0, N_("set ext boot opt"));
|
||||
cmd_unset_bootopt = grub_register_command ("vt_unset_boot_opt", grub_cmd_unset_boot_opt, 0, N_("unset ext boot opt"));
|
||||
|
||||
cmd_extra_initrd_append = grub_register_command ("vt_img_extra_initrd_append", grub_cmd_extra_initrd_append, 0, N_(""));
|
||||
cmd_extra_initrd_reset = grub_register_command ("vt_img_extra_initrd_reset", grub_cmd_extra_initrd_reset, 0, N_(""));
|
||||
|
||||
ventoy_linux_args = grub_zalloc(sizeof(char *) * LINUX_MAX_ARGC);
|
||||
|
||||
my_mod = mod;
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI (linux)
|
||||
{
|
||||
grub_unregister_command (cmd_linux);
|
||||
grub_unregister_command (cmd_initrd);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user