Compare commits
45 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
b53e1fb8a8 | ||
|
84abffc424 | ||
|
bf4e014023 | ||
|
4f840ed673 | ||
|
d02f184a8d | ||
|
774e38928f | ||
|
0faba673a5 | ||
|
3c649b281f | ||
|
5f409a1208 | ||
|
9eb334d99a | ||
|
260a3269b7 | ||
|
a287bf8907 | ||
|
48a1b80be0 | ||
|
b9ef72fbe9 | ||
|
390507fff7 | ||
|
a29bdfbc3c | ||
|
21735f92d6 | ||
|
9a8d4d0227 | ||
|
6ebe77792c | ||
|
d678e54956 | ||
|
8dce0adda6 | ||
|
1bf3e73373 | ||
|
a9996d6761 | ||
|
dafea731c8 | ||
|
6d093e88e7 | ||
|
58a93cdb40 | ||
|
9962775296 | ||
|
062f816020 | ||
|
89b7232b76 | ||
|
1186caba41 | ||
|
be50ea69aa | ||
|
433d854aab | ||
|
4cb9134e5c | ||
|
faceaf4267 | ||
|
37edd5a349 | ||
|
ed0f8721d7 | ||
|
d80a008c04 | ||
|
036e9cc167 | ||
|
26258653b7 | ||
|
754e754412 | ||
|
5af01de7c2 | ||
|
f9763a44b2 | ||
|
d063dbb7f2 | ||
|
89938e3c78 | ||
|
85840f626b |
24
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
name: Ventoy CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Run docker-compose up
|
||||
run: docker-compose up
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ventoy-linux
|
||||
path: INSTALL/ventoy-*linux*
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ventoy-windows
|
||||
path: INSTALL/ventoy-*windows*
|
||||
|
1166
BUSYBOX/64h.config
Normal file
18
BUSYBOX/chmod/build.sh
Normal file
@@ -0,0 +1,18 @@
|
||||
#!/bin/sh
|
||||
|
||||
DSTDIR=../../IMG/cpio/ventoy/busybox
|
||||
|
||||
rm -f vtchmod32 vtchmod64
|
||||
rm -f $DSTDIR/vtchmod32 $DSTDIR/vtchmod64
|
||||
|
||||
/opt/diet32/bin/diet gcc -Os -m32 vtchmod.c -o vtchmod32
|
||||
/opt/diet64/bin/diet gcc -Os vtchmod.c -o vtchmod64
|
||||
|
||||
chmod 777 vtchmod32
|
||||
chmod 777 vtchmod64
|
||||
|
||||
cp -a vtchmod32 $DSTDIR/
|
||||
cp -a vtchmod64 $DSTDIR/
|
||||
|
||||
|
||||
|
13
BUSYBOX/chmod/vtchmod.c
Normal file
@@ -0,0 +1,13 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc != 2)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return chmod(argv[1], 0777);
|
||||
}
|
||||
|
BIN
BUSYBOX/chmod/vtchmod32
Normal file
BIN
BUSYBOX/chmod/vtchmod64
Normal file
@@ -28,4 +28,22 @@ build for 32bit, static linked with dietlibc
|
||||
|
||||
4. make
|
||||
5. strip dmsetup/dmsetup
|
||||
5. get dmsetup/dmsetup as the binary file
|
||||
6. get dmsetup/dmsetup as the dmsetup32 binary file
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
======================== Build for 64bit dmsetup =========================
|
||||
https://www.uclibc.org/downloads/binaries/0.9.30.1/mini-native-x86_64.tar.bz2
|
||||
1. extract device mapper source code
|
||||
2. extract mini-native-x86_64.tar.bz2
|
||||
3. chroot to mini-native-x86_64
|
||||
3. ./configure --disable-nls --disable-selinux --disable-shared --enable-static_link
|
||||
4. make
|
||||
5. strip dmsetup/dmsetup.static
|
||||
6. get dmsetup/dmsetup.static as the dmsetup64 binary file
|
||||
|
||||
|
||||
|
||||
|
BIN
DMSETUP/dmsetup64
Normal file
@@ -127,15 +127,32 @@
|
||||
cd /home/Ventoy-master/GenUUID
|
||||
sh build.sh
|
||||
|
||||
4.15 == Build xzminidec ==
|
||||
cd /home/Ventoy-master/xz-embedded-20130513/userspace
|
||||
4.15 == Build xzminidec32 ==
|
||||
cd /home/Ventoy-master/Ventoy2Disk/Ventoy2Disk/xz-embedded-20130513/userspace
|
||||
make -f ventoy_makefile
|
||||
strip --strip-all xzminidec
|
||||
|
||||
4.16 == Build iso9660_x64.efi ==
|
||||
|
||||
4.16 == Build xzminidec64 ==
|
||||
cd /home/Ventoy-master/Ventoy2Disk/Ventoy2Disk/xz-embedded-20130513/userspace
|
||||
make -f ventoy_makefile64
|
||||
strip --strip-all xzminidec
|
||||
|
||||
4.17 == Build iso9660_x64.efi ==
|
||||
This efi driver is from https://github.com/pbatard/efifs
|
||||
Follow all the build instructions in this project. I modified 3 files (the original and modified source are at /home/Ventoy-master/EDK2/efiffs)
|
||||
|
||||
4.18 IMG/cpio/ventoy/busybox/64h
|
||||
https://www.uclibc.org/downloads/binaries/0.9.30.1/mini-native-x86_64.tar.bz2
|
||||
https://busybox.net/downloads/busybox-1.32.0.tar.bz2
|
||||
use BUSYBOX/64h.config and uclibc to build busybox-1.32
|
||||
|
||||
4.19 == Build lunzip32/lunzip64 ==
|
||||
http://mirror.yongbok.net/nongnu/lzip/lunzip/lunzip-1.11.tar.gz
|
||||
PATH=$PATH:/opt/diet/bin
|
||||
./configure --disable-nls CC='diet gcc -nostdinc'
|
||||
make
|
||||
strip --strip-all lunzip
|
||||
|
||||
|
||||
|
||||
==========================================
|
||||
@@ -156,7 +173,7 @@
|
||||
https://busybox.net/downloads/binaries/1.30.0-i686 busybox_INOTIFYD
|
||||
SHA-256: 3532162a8695e91a1ed9ddea28b2cb22259a90e93d5d9c4a517b6c36842c686f
|
||||
|
||||
5.4 IMG/cpio/ventoy/busybox/tmpsh
|
||||
5.4 IMG/cpio/ventoy/busybox/ash
|
||||
https://busybox.net/downloads/binaries/1.27.1-i686 busybox_ASH
|
||||
SHA-256: 44a6274bca580c2758ffc173fc76d18bb855b1fe8dcf70efd9ee75cbd57dee97
|
||||
|
||||
|
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
|
||||
|
||||
|
||||
|
@@ -37,6 +37,7 @@
|
||||
#include <Ventoy.h>
|
||||
|
||||
BOOLEAN gDebugPrint = FALSE;
|
||||
BOOLEAN gDotEfiBoot = FALSE;
|
||||
BOOLEAN gLoadIsoEfi = FALSE;
|
||||
ventoy_ram_disk g_ramdisk_param;
|
||||
ventoy_chain_head *g_chain;
|
||||
@@ -49,6 +50,7 @@ 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;
|
||||
@@ -271,19 +273,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;
|
||||
@@ -331,7 +347,7 @@ EFI_STATUS EFIAPI ventoy_save_ramdisk_param(VOID)
|
||||
Status = gRT->SetVariable(L"VentoyRamDisk", &VarGuid,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
|
||||
sizeof(g_ramdisk_param), &(g_ramdisk_param));
|
||||
debug("set efi variable %r", Status);
|
||||
debug("set ramdisk variable %r", Status);
|
||||
|
||||
return Status;
|
||||
}
|
||||
@@ -376,6 +392,36 @@ EFI_STATUS EFIAPI ventoy_delete_variable(VOID)
|
||||
return Status;
|
||||
}
|
||||
|
||||
#if (VENTOY_DEVICE_WARN != 0)
|
||||
STATIC VOID ventoy_warn_invalid_device(VOID)
|
||||
{
|
||||
STATIC BOOLEAN flag = FALSE;
|
||||
|
||||
if (flag)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
flag = TRUE;
|
||||
gST->ConOut->ClearScreen(gST->ConOut);
|
||||
gST->ConOut->OutputString(gST->ConOut, VTOY_WARNING L"\r\n");
|
||||
gST->ConOut->OutputString(gST->ConOut, VTOY_WARNING L"\r\n");
|
||||
gST->ConOut->OutputString(gST->ConOut, VTOY_WARNING L"\r\n\r\n\r\n");
|
||||
|
||||
gST->ConOut->OutputString(gST->ConOut, L"This is NOT a standard Ventoy device and is NOT officially 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 continue to boot after 15 seconds ...... ");
|
||||
|
||||
sleep(15);
|
||||
}
|
||||
#else
|
||||
STATIC VOID ventoy_warn_invalid_device(VOID)
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
STATIC EFI_STATUS EFIAPI ventoy_load_image
|
||||
(
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
@@ -418,6 +464,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;
|
||||
@@ -461,6 +508,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,
|
||||
@@ -580,6 +639,7 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
|
||||
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;
|
||||
@@ -602,6 +662,11 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
|
||||
{
|
||||
gDebugPrint = TRUE;
|
||||
}
|
||||
|
||||
if (StrStr(pCmdLine, L"dotefi"))
|
||||
{
|
||||
gDotEfiBoot = TRUE;
|
||||
}
|
||||
|
||||
if (StrStr(pCmdLine, L"isoefi=on"))
|
||||
{
|
||||
@@ -642,8 +707,19 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
|
||||
}
|
||||
|
||||
pGrubParam = (ventoy_grub_param *)StrHexToUintn(pPos + StrLen(L"env_param="));
|
||||
grub_env_set = pGrubParam->grub_env_set;
|
||||
grub_env_get = pGrubParam->grub_env_get;
|
||||
pEnv = grub_env_get("VTOY_CHKDEV_RESULT_STRING");
|
||||
if (!pEnv)
|
||||
{
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (pEnv[0] != '0' || pEnv[1] != 0)
|
||||
{
|
||||
ventoy_warn_invalid_device();
|
||||
}
|
||||
|
||||
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>",
|
||||
@@ -663,17 +739,27 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
|
||||
size = StrDecimalToUintn(pPos + 5);
|
||||
|
||||
debug("memory addr:%p size:%lu", chain, size);
|
||||
|
||||
g_chain = AllocatePool(size);
|
||||
CopyMem(g_chain, chain, size);
|
||||
|
||||
if (StrStr(pCmdLine, L"sector512"))
|
||||
{
|
||||
gSector512Mode = TRUE;
|
||||
}
|
||||
|
||||
if (StrStr(pCmdLine, L"memdisk"))
|
||||
{
|
||||
g_iso_buf_size = size;
|
||||
g_iso_data_buf = (UINT8 *)chain + sizeof(ventoy_chain_head);
|
||||
g_iso_buf_size = size - sizeof(ventoy_chain_head);
|
||||
debug("memdisk mode iso_buf_size:%u", g_iso_buf_size);
|
||||
|
||||
g_chain = chain;
|
||||
gMemdiskMode = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("This is normal mode");
|
||||
g_chain = AllocatePool(size);
|
||||
CopyMem(g_chain, chain, size);
|
||||
|
||||
g_chunk = (ventoy_img_chunk *)((char *)g_chain + g_chain->img_chunk_offset);
|
||||
g_img_chunk_num = g_chain->img_chunk_num;
|
||||
g_override_chunk = (ventoy_override_chunk *)((char *)g_chain + g_chain->override_chunk_offset);
|
||||
@@ -725,6 +811,8 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
|
||||
}
|
||||
}
|
||||
|
||||
ventoy_debug_pause();
|
||||
|
||||
FreePool(pCmdLine);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
@@ -899,6 +987,11 @@ EFI_STATUS EFIAPI ventoy_boot(IN EFI_HANDLE ImageHandle)
|
||||
|
||||
if (Find == 0)
|
||||
{
|
||||
if (gDotEfiBoot)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
debug("Fs not found, now wait and retry...");
|
||||
sleep(2);
|
||||
}
|
||||
@@ -938,52 +1031,86 @@ EFI_STATUS EFIAPI VentoyEfiMain
|
||||
gST->ConOut->ClearScreen(gST->ConOut);
|
||||
ventoy_clear_input();
|
||||
|
||||
ventoy_parse_cmdline(ImageHandle);
|
||||
Status = ventoy_parse_cmdline(ImageHandle);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (gMemdiskMode)
|
||||
{
|
||||
g_ramdisk_param.PhyAddr = (UINT64)(UINTN)g_chain;
|
||||
g_ramdisk_param.PhyAddr = (UINT64)(UINTN)g_iso_data_buf;
|
||||
g_ramdisk_param.DiskSize = (UINT64)g_iso_buf_size;
|
||||
|
||||
ventoy_save_ramdisk_param();
|
||||
|
||||
if (gLoadIsoEfi)
|
||||
{
|
||||
ventoy_find_iso_disk(ImageHandle);
|
||||
ventoy_find_iso_disk_fs(ImageHandle);
|
||||
ventoy_load_isoefi_driver(ImageHandle);
|
||||
}
|
||||
|
||||
ventoy_install_blockio(ImageHandle, g_iso_buf_size);
|
||||
ventoy_debug_pause();
|
||||
|
||||
Status = ventoy_boot(ImageHandle);
|
||||
|
||||
ventoy_delete_ramdisk_param();
|
||||
|
||||
if (gLoadIsoEfi && gBlockData.IsoDriverImage)
|
||||
{
|
||||
gBS->UnloadImage(gBlockData.IsoDriverImage);
|
||||
}
|
||||
|
||||
gBS->DisconnectController(gBlockData.Handle, NULL, NULL);
|
||||
gBS->UninstallMultipleProtocolInterfaces(gBlockData.Handle,
|
||||
&gEfiBlockIoProtocolGuid, &gBlockData.BlockIo,
|
||||
&gEfiDevicePathProtocolGuid, gBlockData.Path,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
ventoy_save_variable();
|
||||
ventoy_find_iso_disk(ImageHandle);
|
||||
|
||||
if (gLoadIsoEfi)
|
||||
Status = ventoy_find_iso_disk(ImageHandle);
|
||||
if (!EFI_ERROR(Status))
|
||||
{
|
||||
ventoy_find_iso_disk_fs(ImageHandle);
|
||||
ventoy_load_isoefi_driver(ImageHandle);
|
||||
if (gLoadIsoEfi)
|
||||
{
|
||||
ventoy_find_iso_disk_fs(ImageHandle);
|
||||
ventoy_load_isoefi_driver(ImageHandle);
|
||||
}
|
||||
|
||||
ventoy_debug_pause();
|
||||
|
||||
ventoy_install_blockio(ImageHandle, g_chain->virt_img_size_in_bytes);
|
||||
|
||||
ventoy_debug_pause();
|
||||
|
||||
Status = ventoy_boot(ImageHandle);
|
||||
}
|
||||
|
||||
ventoy_debug_pause();
|
||||
|
||||
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)
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
@@ -185,6 +185,9 @@ typedef struct ventoy_virt_chunk
|
||||
#error Unknown Processor Type
|
||||
#endif
|
||||
|
||||
#define VENTOY_DEVICE_WARN 0
|
||||
#define VTOY_WARNING L"!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!"
|
||||
|
||||
typedef struct ventoy_sector_flag
|
||||
{
|
||||
UINT8 flag; // 0:init 1:mem 2:remap
|
||||
@@ -227,6 +230,7 @@ if (gDebugPrint) \
|
||||
gBS->WaitForEvent(1, &gST->ConIn->WaitForKey, &__Index);\
|
||||
}
|
||||
|
||||
typedef int (*grub_env_set_pf)(const char *name, const char *val);
|
||||
typedef const char * (*grub_env_get_pf)(const char *name);
|
||||
typedef int (*grub_env_printf_pf)(const char *fmt, ...);
|
||||
|
||||
@@ -255,6 +259,7 @@ typedef struct ventoy_grub_param_file_replace
|
||||
typedef struct ventoy_grub_param
|
||||
{
|
||||
grub_env_get_pf grub_env_get;
|
||||
grub_env_set_pf grub_env_set;
|
||||
ventoy_grub_param_file_replace file_replace;
|
||||
grub_env_printf_pf grub_env_printf;
|
||||
}ventoy_grub_param;
|
||||
@@ -273,6 +278,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()
|
||||
|
||||
|
||||
@@ -338,7 +369,9 @@ extern ventoy_efi_file_replace g_efi_file_replace;
|
||||
extern ventoy_sector_flag *g_sector_flag;
|
||||
extern UINT32 g_sector_flag_num;
|
||||
extern BOOLEAN gMemdiskMode;
|
||||
extern BOOLEAN gSector512Mode;
|
||||
extern UINTN g_iso_buf_size;
|
||||
extern UINT8 *g_iso_data_buf;
|
||||
extern ventoy_grub_param_file_replace *g_file_replace_list;
|
||||
extern BOOLEAN g_fixup_iso9660_secover_enable;
|
||||
extern EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *g_con_simple_input_ex;
|
||||
|
@@ -36,8 +36,10 @@
|
||||
#include <Protocol/SimpleFileSystem.h>
|
||||
#include <Ventoy.h>
|
||||
|
||||
UINT8 *g_iso_data_buf = NULL;
|
||||
UINTN g_iso_buf_size = 0;
|
||||
BOOLEAN gMemdiskMode = FALSE;
|
||||
BOOLEAN gSector512Mode = FALSE;
|
||||
|
||||
ventoy_sector_flag *g_sector_flag = NULL;
|
||||
UINT32 g_sector_flag_num = 0;
|
||||
@@ -67,6 +69,10 @@ STATIC EFI_INPUT_READ_KEY g_org_read_key = NULL;
|
||||
|
||||
STATIC EFI_LOCATE_HANDLE g_org_locate_handle = NULL;
|
||||
|
||||
STATIC UINT8 g_sector_buf[2048];
|
||||
STATIC EFI_BLOCK_READ g_sector_2048_read = NULL;
|
||||
STATIC EFI_BLOCK_WRITE g_sector_2048_write = NULL;
|
||||
|
||||
BOOLEAN ventoy_is_cdrom_dp_exist(VOID)
|
||||
{
|
||||
UINTN i = 0;
|
||||
@@ -240,6 +246,87 @@ 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
|
||||
{
|
||||
MapLba = (Sector - pchunk->img_start_sector) * 2048 / g_chain->disk_sector_size + pchunk->disk_start_sector;
|
||||
}
|
||||
|
||||
secLeft = pchunk->img_end_sector + 1 - Sector;
|
||||
secRead = (Count < secLeft) ? Count : secLeft;
|
||||
|
||||
Status = pRawBlockIo->WriteBlocks(pRawBlockIo, pRawBlockIo->Media->MediaId,
|
||||
MapLba, secRead * 2048, pCurBuf);
|
||||
if (EFI_ERROR(Status))
|
||||
{
|
||||
debug("Raw disk write block failed %r LBA:%lu Count:%u", Status, MapLba, secRead);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Count -= secRead;
|
||||
Sector += secRead;
|
||||
pCurBuf += secRead * 2048;
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_block_io_ramdisk_write
|
||||
(
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSize,
|
||||
IN VOID *Buffer
|
||||
)
|
||||
{
|
||||
(VOID)This;
|
||||
(VOID)MediaId;
|
||||
(VOID)Lba;
|
||||
(VOID)BufferSize;
|
||||
(VOID)Buffer;
|
||||
|
||||
if (!gSector512Mode)
|
||||
{
|
||||
return EFI_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
CopyMem(g_iso_data_buf + (Lba * 2048), Buffer, BufferSize);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_block_io_ramdisk_read
|
||||
(
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
@@ -254,7 +341,7 @@ EFI_STATUS EFIAPI ventoy_block_io_ramdisk_read
|
||||
(VOID)This;
|
||||
(VOID)MediaId;
|
||||
|
||||
CopyMem(Buffer, (char *)g_chain + (Lba * 2048), BufferSize);
|
||||
CopyMem(Buffer, g_iso_data_buf + (Lba * 2048), BufferSize);
|
||||
|
||||
if (g_blockio_start_record_bcd && FALSE == g_blockio_bcd_read_done)
|
||||
{
|
||||
@@ -433,12 +520,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)
|
||||
@@ -570,6 +666,126 @@ end:
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_block_io_read_512
|
||||
(
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSize,
|
||||
OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
EFI_LBA Mod;
|
||||
UINTN ReadSize;
|
||||
UINT8 *CurBuf = NULL;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
|
||||
debug("ventoy_block_io_read_512 %lu %lu\n", Lba, BufferSize / 512);
|
||||
|
||||
CurBuf = (UINT8 *)Buffer;
|
||||
|
||||
Mod = Lba % 4;
|
||||
if (Mod > 0)
|
||||
{
|
||||
Status |= g_sector_2048_read(This, MediaId, Lba / 4, 2048, g_sector_buf);
|
||||
|
||||
if (BufferSize <= (4 - Mod) * 512)
|
||||
{
|
||||
CopyMem(CurBuf, g_sector_buf + Mod * 512, BufferSize);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
ReadSize = (4 - Mod) * 512;
|
||||
CopyMem(CurBuf, g_sector_buf + Mod * 512, ReadSize);
|
||||
CurBuf += ReadSize;
|
||||
Lba += (4 - Mod);
|
||||
BufferSize -= ReadSize;
|
||||
}
|
||||
}
|
||||
|
||||
if (BufferSize >= 2048)
|
||||
{
|
||||
ReadSize = BufferSize / 2048 * 2048;
|
||||
|
||||
Status |= g_sector_2048_read(This, MediaId, Lba / 4, ReadSize, CurBuf);
|
||||
CurBuf += ReadSize;
|
||||
|
||||
Lba += ReadSize / 512;
|
||||
BufferSize -= ReadSize;
|
||||
}
|
||||
|
||||
if (BufferSize > 0)
|
||||
{
|
||||
Status |= g_sector_2048_read(This, MediaId, Lba / 4, 2048, g_sector_buf);
|
||||
CopyMem(CurBuf, g_sector_buf, BufferSize);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_block_io_write_512
|
||||
(
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSize,
|
||||
IN VOID *Buffer
|
||||
)
|
||||
{
|
||||
EFI_LBA Mod;
|
||||
UINTN ReadSize;
|
||||
UINT8 *CurBuf = NULL;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
|
||||
debug("ventoy_block_io_write_512 %lu %lu\n", Lba, BufferSize / 512);
|
||||
|
||||
CurBuf = (UINT8 *)Buffer;
|
||||
|
||||
Mod = Lba % 4;
|
||||
if (Mod > 0)
|
||||
{
|
||||
Status |= g_sector_2048_read(This, MediaId, Lba / 4, 2048, g_sector_buf);
|
||||
|
||||
if (BufferSize <= (4 - Mod) * 512)
|
||||
{
|
||||
CopyMem(g_sector_buf + Mod * 512, CurBuf, BufferSize);
|
||||
return g_sector_2048_write(This, MediaId, Lba / 4, 2048, g_sector_buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
ReadSize = (4 - Mod) * 512;
|
||||
CopyMem(g_sector_buf + Mod * 512, CurBuf, ReadSize);
|
||||
g_sector_2048_write(This, MediaId, Lba / 4, 2048, g_sector_buf);
|
||||
|
||||
CurBuf += ReadSize;
|
||||
Lba += (4 - Mod);
|
||||
BufferSize -= ReadSize;
|
||||
}
|
||||
}
|
||||
|
||||
if (BufferSize >= 2048)
|
||||
{
|
||||
ReadSize = BufferSize / 2048 * 2048;
|
||||
|
||||
Status |= g_sector_2048_write(This, MediaId, Lba / 4, ReadSize, CurBuf);
|
||||
CurBuf += ReadSize;
|
||||
|
||||
Lba += ReadSize / 512;
|
||||
BufferSize -= ReadSize;
|
||||
}
|
||||
|
||||
if (BufferSize > 0)
|
||||
{
|
||||
Status |= g_sector_2048_read(This, MediaId, Lba / 4, 2048, g_sector_buf);
|
||||
|
||||
CopyMem(g_sector_buf, CurBuf, BufferSize);
|
||||
g_sector_2048_write(This, MediaId, Lba / 4, 2048, g_sector_buf);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI ventoy_install_blockio(IN EFI_HANDLE ImageHandle, IN UINT64 ImgSize)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
@@ -579,9 +795,18 @@ EFI_STATUS EFIAPI ventoy_install_blockio(IN EFI_HANDLE ImageHandle, IN UINT64 Im
|
||||
|
||||
debug("install block io protocol %p", ImageHandle);
|
||||
ventoy_debug_pause();
|
||||
|
||||
if (gSector512Mode)
|
||||
{
|
||||
gBlockData.Media.BlockSize = 512;
|
||||
gBlockData.Media.LastBlock = ImgSize / 512 - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
gBlockData.Media.BlockSize = 2048;
|
||||
gBlockData.Media.LastBlock = ImgSize / 2048 - 1;
|
||||
}
|
||||
|
||||
gBlockData.Media.BlockSize = 2048;
|
||||
gBlockData.Media.LastBlock = ImgSize / 2048 - 1;
|
||||
gBlockData.Media.ReadOnly = TRUE;
|
||||
gBlockData.Media.MediaPresent = 1;
|
||||
gBlockData.Media.LogicalBlocksPerPhysicalBlock = 1;
|
||||
@@ -589,8 +814,20 @@ EFI_STATUS EFIAPI ventoy_install_blockio(IN EFI_HANDLE ImageHandle, IN UINT64 Im
|
||||
pBlockIo->Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3;
|
||||
pBlockIo->Media = &(gBlockData.Media);
|
||||
pBlockIo->Reset = ventoy_block_io_reset;
|
||||
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,
|
||||
@@ -602,10 +839,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);
|
||||
|
||||
|
||||
Status = ventoy_connect_driver(gBlockData.Handle, L"Partition Driver");
|
||||
debug("Connect partition driver %r", Status);
|
||||
if (EFI_ERROR(Status))
|
||||
|
@@ -24,6 +24,7 @@
|
||||
#pragma pack(1)
|
||||
|
||||
typedef EFI_STATUS (*VTOY_UTIL_PROC_PF)(IN EFI_HANDLE ImageHandle, IN CONST CHAR16 *CmdLine);
|
||||
typedef int (*grub_env_set_pf)(const char *name, const char *val);
|
||||
typedef const char * (*grub_env_get_pf)(const char *name);
|
||||
typedef int (*grub_env_printf_pf)(const char *fmt, ...);
|
||||
|
||||
@@ -38,6 +39,7 @@ typedef struct ventoy_grub_param_file_replace
|
||||
typedef struct ventoy_grub_param
|
||||
{
|
||||
grub_env_get_pf grub_env_get;
|
||||
grub_env_set_pf grub_env_set;
|
||||
ventoy_grub_param_file_replace file_replace;
|
||||
grub_env_printf_pf grub_env_printf;
|
||||
}ventoy_grub_param;
|
||||
|
1
EfiISO/ISO/EFI/BOOT/BOOTX64.EFI
Normal file
@@ -0,0 +1 @@
|
||||
1
|
13
EfiISO/mkefiiso.sh
Normal file
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
rm -f ventoy_efiboot.img.*
|
||||
|
||||
cd ISO
|
||||
mkisofs -R -D -sysid VENTOY -V VENTOY -P "longpanda admin@ventoy.net" -p 'https://www.ventoy.net' -o ../ventoy_efiboot.img ./
|
||||
cd ..
|
||||
|
||||
xz --check=crc32 ventoy_efiboot.img
|
||||
|
||||
rm -f ../INSTALL/ventoy/ventoy_efiboot.img.xz
|
||||
cp -a ventoy_efiboot.img.xz ../INSTALL/ventoy/
|
||||
|
@@ -114,11 +114,12 @@ static int ventoy_iso_open(const char *path, struct fuse_file_info *file)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ventoy_read_iso_sector(uint32_t sector, uint32_t num, void *buf)
|
||||
static int ventoy_read_iso_sector(uint32_t sector, uint32_t num, char *buf)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint32_t leftSec = 0;
|
||||
uint32_t readSec = 0;
|
||||
off_t offset = 0;
|
||||
dmtable_entry *entry = NULL;
|
||||
|
||||
for (i = 0; i < g_disk_entry_num && num > 0; i++)
|
||||
@@ -127,14 +128,15 @@ static int ventoy_read_iso_sector(uint32_t sector, uint32_t num, void *buf)
|
||||
|
||||
if (sector >= entry->isoSector && sector < entry->isoSector + entry->sectorNum)
|
||||
{
|
||||
lseek(g_disk_fd, (entry->diskSector + (sector - entry->isoSector)) * 512, SEEK_SET);
|
||||
offset = (entry->diskSector + (sector - entry->isoSector)) * 512;
|
||||
|
||||
leftSec = entry->sectorNum - (sector - entry->isoSector);
|
||||
readSec = (leftSec > num) ? num : leftSec;
|
||||
|
||||
read(g_disk_fd, buf, readSec * 512);
|
||||
pread(g_disk_fd, buf, readSec * 512, offset);
|
||||
|
||||
sector += readSec;
|
||||
buf += readSec * 512;
|
||||
num -= readSec;
|
||||
}
|
||||
}
|
||||
|
@@ -809,6 +809,16 @@ module = {
|
||||
common = commands/blocklist.c;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = blscfg;
|
||||
common = commands/blscfg.c;
|
||||
common = commands/loadenv.h;
|
||||
enable = powerpc_ieee1275;
|
||||
enable = efi;
|
||||
enable = i386_pc;
|
||||
enable = emu;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = boot;
|
||||
common = commands/boot.c;
|
||||
@@ -986,6 +996,7 @@ module = {
|
||||
module = {
|
||||
name = loadenv;
|
||||
common = commands/loadenv.c;
|
||||
common = commands/loadenv.h;
|
||||
common = lib/envblk.c;
|
||||
};
|
||||
|
||||
@@ -1578,7 +1589,9 @@ module = {
|
||||
name = ventoy;
|
||||
common = ventoy/ventoy.c;
|
||||
common = ventoy/ventoy_linux.c;
|
||||
common = ventoy/ventoy_unix.c;
|
||||
common = ventoy/ventoy_windows.c;
|
||||
common = ventoy/ventoy_vhd.c;
|
||||
common = ventoy/ventoy_plugin.c;
|
||||
common = ventoy/ventoy_json.c;
|
||||
common = ventoy/lzx.c;
|
||||
|
1111
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/blscfg.c
Normal file
894
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/legacycfg.c
Normal file
@@ -0,0 +1,894 @@
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2000, 2001, 2010 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/types.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/script_sh.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/legacy_parse.h>
|
||||
#include <grub/crypto.h>
|
||||
#include <grub/auth.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/partition.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
/* Helper for legacy_file. */
|
||||
static grub_err_t
|
||||
legacy_file_getline (char **line, int cont __attribute__ ((unused)),
|
||||
void *data __attribute__ ((unused)))
|
||||
{
|
||||
*line = 0;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
legacy_file (const char *filename)
|
||||
{
|
||||
grub_file_t file;
|
||||
char *entryname = NULL, *entrysrc = NULL;
|
||||
grub_menu_t menu;
|
||||
char *suffix = grub_strdup ("");
|
||||
|
||||
if (!suffix)
|
||||
return grub_errno;
|
||||
|
||||
file = grub_file_open (filename, GRUB_FILE_TYPE_CONFIG);
|
||||
if (! file)
|
||||
{
|
||||
grub_free (suffix);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
menu = grub_env_get_menu ();
|
||||
if (! menu)
|
||||
{
|
||||
menu = grub_zalloc (sizeof (*menu));
|
||||
if (! menu)
|
||||
{
|
||||
grub_free (suffix);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
grub_env_set_menu (menu);
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
char *buf = grub_file_getline (file);
|
||||
char *parsed = NULL;
|
||||
|
||||
if (!buf && grub_errno)
|
||||
{
|
||||
grub_file_close (file);
|
||||
grub_free (suffix);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
if (!buf)
|
||||
break;
|
||||
|
||||
{
|
||||
char *oldname = NULL;
|
||||
char *newsuffix;
|
||||
char *ptr;
|
||||
|
||||
for (ptr = buf; *ptr && grub_isspace (*ptr); ptr++);
|
||||
|
||||
oldname = entryname;
|
||||
parsed = grub_legacy_parse (ptr, &entryname, &newsuffix);
|
||||
grub_free (buf);
|
||||
buf = NULL;
|
||||
if (newsuffix)
|
||||
{
|
||||
char *t;
|
||||
|
||||
t = suffix;
|
||||
suffix = grub_realloc (suffix, grub_strlen (suffix)
|
||||
+ grub_strlen (newsuffix) + 1);
|
||||
if (!suffix)
|
||||
{
|
||||
grub_free (t);
|
||||
grub_free (entrysrc);
|
||||
grub_free (parsed);
|
||||
grub_free (newsuffix);
|
||||
grub_free (suffix);
|
||||
return grub_errno;
|
||||
}
|
||||
grub_memcpy (suffix + grub_strlen (suffix), newsuffix,
|
||||
grub_strlen (newsuffix) + 1);
|
||||
grub_free (newsuffix);
|
||||
newsuffix = NULL;
|
||||
}
|
||||
if (oldname != entryname && oldname)
|
||||
{
|
||||
const char **args = grub_malloc (sizeof (args[0]));
|
||||
if (!args)
|
||||
{
|
||||
grub_file_close (file);
|
||||
return grub_errno;
|
||||
}
|
||||
args[0] = oldname;
|
||||
grub_normal_add_menu_entry (1, args, NULL, NULL, "legacy",
|
||||
NULL, NULL,
|
||||
entrysrc, 0, NULL, NULL);
|
||||
grub_free (args);
|
||||
entrysrc[0] = 0;
|
||||
grub_free (oldname);
|
||||
}
|
||||
}
|
||||
|
||||
if (parsed && !entryname)
|
||||
{
|
||||
grub_normal_parse_line (parsed, legacy_file_getline, NULL);
|
||||
grub_print_error ();
|
||||
grub_free (parsed);
|
||||
parsed = NULL;
|
||||
}
|
||||
else if (parsed)
|
||||
{
|
||||
if (!entrysrc)
|
||||
entrysrc = parsed;
|
||||
else
|
||||
{
|
||||
char *t;
|
||||
|
||||
t = entrysrc;
|
||||
entrysrc = grub_realloc (entrysrc, grub_strlen (entrysrc)
|
||||
+ grub_strlen (parsed) + 1);
|
||||
if (!entrysrc)
|
||||
{
|
||||
grub_free (t);
|
||||
grub_free (parsed);
|
||||
grub_free (suffix);
|
||||
return grub_errno;
|
||||
}
|
||||
grub_memcpy (entrysrc + grub_strlen (entrysrc), parsed,
|
||||
grub_strlen (parsed) + 1);
|
||||
grub_free (parsed);
|
||||
parsed = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
grub_file_close (file);
|
||||
|
||||
if (entryname)
|
||||
{
|
||||
const char **args = grub_malloc (sizeof (args[0]));
|
||||
if (!args)
|
||||
{
|
||||
grub_file_close (file);
|
||||
grub_free (suffix);
|
||||
grub_free (entrysrc);
|
||||
return grub_errno;
|
||||
}
|
||||
args[0] = entryname;
|
||||
grub_normal_add_menu_entry (1, args, NULL, NULL, NULL,
|
||||
NULL, NULL, entrysrc, 0, NULL,
|
||||
NULL);
|
||||
grub_free (args);
|
||||
}
|
||||
|
||||
grub_normal_parse_line (suffix, legacy_file_getline, NULL);
|
||||
grub_print_error ();
|
||||
grub_free (suffix);
|
||||
grub_free (entrysrc);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_legacy_source (struct grub_command *cmd,
|
||||
int argc, char **args)
|
||||
{
|
||||
int new_env, extractor;
|
||||
grub_err_t ret;
|
||||
|
||||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
||||
|
||||
extractor = (cmd->name[0] == 'e');
|
||||
new_env = (cmd->name[extractor ? (sizeof ("extract_legacy_entries_") - 1)
|
||||
: (sizeof ("legacy_") - 1)] == 'c');
|
||||
|
||||
if (new_env)
|
||||
grub_cls ();
|
||||
|
||||
if (new_env && !extractor)
|
||||
grub_env_context_open ();
|
||||
if (extractor)
|
||||
grub_env_extractor_open (!new_env);
|
||||
|
||||
ret = legacy_file (args[0]);
|
||||
|
||||
if (new_env)
|
||||
{
|
||||
grub_menu_t menu;
|
||||
menu = grub_env_get_menu ();
|
||||
if (menu && menu->size)
|
||||
grub_show_menu (menu, 1, 0);
|
||||
if (!extractor)
|
||||
grub_env_context_close ();
|
||||
}
|
||||
if (extractor)
|
||||
grub_env_extractor_close (!new_env);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static enum
|
||||
{
|
||||
GUESS_IT, LINUX, MULTIBOOT, KFREEBSD, KNETBSD, KOPENBSD
|
||||
} kernel_type;
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
int i;
|
||||
#ifdef TODO
|
||||
int no_mem_option = 0;
|
||||
#endif
|
||||
struct grub_command *cmd;
|
||||
char **cutargs;
|
||||
int cutargc;
|
||||
grub_err_t err = GRUB_ERR_NONE;
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
/* FIXME: really support this. */
|
||||
if (argc >= 1 && grub_strcmp (args[0], "--no-mem-option") == 0)
|
||||
{
|
||||
#ifdef TODO
|
||||
no_mem_option = 1;
|
||||
#endif
|
||||
argc--;
|
||||
args++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* linux16 handles both zImages and bzImages. */
|
||||
if (argc >= 1 && (grub_strcmp (args[0], "--type=linux") == 0
|
||||
|| grub_strcmp (args[0], "--type=biglinux") == 0))
|
||||
{
|
||||
kernel_type = LINUX;
|
||||
argc--;
|
||||
args++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argc >= 1 && grub_strcmp (args[0], "--type=multiboot") == 0)
|
||||
{
|
||||
kernel_type = MULTIBOOT;
|
||||
argc--;
|
||||
args++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argc >= 1 && grub_strcmp (args[0], "--type=freebsd") == 0)
|
||||
{
|
||||
kernel_type = KFREEBSD;
|
||||
argc--;
|
||||
args++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argc >= 1 && grub_strcmp (args[0], "--type=openbsd") == 0)
|
||||
{
|
||||
kernel_type = KOPENBSD;
|
||||
argc--;
|
||||
args++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argc >= 1 && grub_strcmp (args[0], "--type=netbsd") == 0)
|
||||
{
|
||||
kernel_type = KNETBSD;
|
||||
argc--;
|
||||
args++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc < 2)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
||||
|
||||
cutargs = grub_malloc (sizeof (cutargs[0]) * (argc - 1));
|
||||
if (!cutargs)
|
||||
return grub_errno;
|
||||
cutargc = argc - 1;
|
||||
grub_memcpy (cutargs + 1, args + 2, sizeof (cutargs[0]) * (argc - 2));
|
||||
cutargs[0] = args[0];
|
||||
|
||||
do
|
||||
{
|
||||
/* First try Linux. */
|
||||
if (kernel_type == GUESS_IT || kernel_type == LINUX)
|
||||
{
|
||||
#ifdef GRUB_MACHINE_PCBIOS
|
||||
cmd = grub_command_find ("linux16");
|
||||
#else
|
||||
cmd = grub_command_find ("linux");
|
||||
#endif
|
||||
if (cmd)
|
||||
{
|
||||
if (!(cmd->func) (cmd, cutargc, cutargs))
|
||||
{
|
||||
kernel_type = LINUX;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
/* Then multiboot. */
|
||||
if (kernel_type == GUESS_IT || kernel_type == MULTIBOOT)
|
||||
{
|
||||
cmd = grub_command_find ("multiboot");
|
||||
if (cmd)
|
||||
{
|
||||
if (!(cmd->func) (cmd, argc, args))
|
||||
{
|
||||
kernel_type = MULTIBOOT;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
{
|
||||
int bsd_device = -1;
|
||||
int bsd_slice = -1;
|
||||
int bsd_part = -1;
|
||||
{
|
||||
grub_device_t dev;
|
||||
const char *hdbiasstr;
|
||||
int hdbias = 0;
|
||||
hdbiasstr = grub_env_get ("legacy_hdbias");
|
||||
if (hdbiasstr)
|
||||
{
|
||||
hdbias = grub_strtoul (hdbiasstr, 0, 0);
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
dev = grub_device_open (0);
|
||||
if (dev && dev->disk
|
||||
&& dev->disk->dev->id == GRUB_DISK_DEVICE_BIOSDISK_ID
|
||||
&& dev->disk->id >= 0x80 && dev->disk->id <= 0x90)
|
||||
{
|
||||
struct grub_partition *part = dev->disk->partition;
|
||||
bsd_device = dev->disk->id - 0x80 - hdbias;
|
||||
if (part && (grub_strcmp (part->partmap->name, "netbsd") == 0
|
||||
|| grub_strcmp (part->partmap->name, "openbsd") == 0
|
||||
|| grub_strcmp (part->partmap->name, "bsd") == 0))
|
||||
{
|
||||
bsd_part = part->number;
|
||||
part = part->parent;
|
||||
}
|
||||
if (part && grub_strcmp (part->partmap->name, "msdos") == 0)
|
||||
bsd_slice = part->number;
|
||||
}
|
||||
if (dev)
|
||||
grub_device_close (dev);
|
||||
}
|
||||
|
||||
/* k*BSD didn't really work well with grub-legacy. */
|
||||
if (kernel_type == GUESS_IT || kernel_type == KFREEBSD)
|
||||
{
|
||||
char buf[sizeof("adXXXXXXXXXXXXsXXXXXXXXXXXXYYY")];
|
||||
if (bsd_device != -1)
|
||||
{
|
||||
if (bsd_slice != -1 && bsd_part != -1)
|
||||
grub_snprintf(buf, sizeof(buf), "ad%ds%d%c", bsd_device,
|
||||
bsd_slice, 'a' + bsd_part);
|
||||
else if (bsd_slice != -1)
|
||||
grub_snprintf(buf, sizeof(buf), "ad%ds%d", bsd_device,
|
||||
bsd_slice);
|
||||
else
|
||||
grub_snprintf(buf, sizeof(buf), "ad%d", bsd_device);
|
||||
grub_env_set ("kFreeBSD.vfs.root.mountfrom", buf);
|
||||
}
|
||||
else
|
||||
grub_env_unset ("kFreeBSD.vfs.root.mountfrom");
|
||||
cmd = grub_command_find ("kfreebsd");
|
||||
if (cmd)
|
||||
{
|
||||
if (!(cmd->func) (cmd, cutargc, cutargs))
|
||||
{
|
||||
kernel_type = KFREEBSD;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
{
|
||||
char **bsdargs;
|
||||
int bsdargc;
|
||||
char bsddevname[sizeof ("wdXXXXXXXXXXXXY")];
|
||||
int found = 0;
|
||||
|
||||
if (bsd_device == -1)
|
||||
{
|
||||
bsdargs = cutargs;
|
||||
bsdargc = cutargc;
|
||||
}
|
||||
else
|
||||
{
|
||||
char rbuf[3] = "-r";
|
||||
bsdargc = cutargc + 2;
|
||||
bsdargs = grub_malloc (sizeof (bsdargs[0]) * bsdargc);
|
||||
if (!bsdargs)
|
||||
{
|
||||
err = grub_errno;
|
||||
goto out;
|
||||
}
|
||||
grub_memcpy (bsdargs, args, argc * sizeof (bsdargs[0]));
|
||||
bsdargs[argc] = rbuf;
|
||||
bsdargs[argc + 1] = bsddevname;
|
||||
grub_snprintf (bsddevname, sizeof (bsddevname),
|
||||
"wd%d%c", bsd_device,
|
||||
bsd_part != -1 ? bsd_part + 'a' : 'c');
|
||||
}
|
||||
if (kernel_type == GUESS_IT || kernel_type == KNETBSD)
|
||||
{
|
||||
cmd = grub_command_find ("knetbsd");
|
||||
if (cmd)
|
||||
{
|
||||
if (!(cmd->func) (cmd, bsdargc, bsdargs))
|
||||
{
|
||||
kernel_type = KNETBSD;
|
||||
found = 1;
|
||||
goto free_bsdargs;
|
||||
}
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
if (kernel_type == GUESS_IT || kernel_type == KOPENBSD)
|
||||
{
|
||||
cmd = grub_command_find ("kopenbsd");
|
||||
if (cmd)
|
||||
{
|
||||
if (!(cmd->func) (cmd, bsdargc, bsdargs))
|
||||
{
|
||||
kernel_type = KOPENBSD;
|
||||
found = 1;
|
||||
goto free_bsdargs;
|
||||
}
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
free_bsdargs:
|
||||
if (bsdargs != cutargs)
|
||||
grub_free (bsdargs);
|
||||
if (found)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (0);
|
||||
|
||||
err = grub_error (GRUB_ERR_BAD_OS, "couldn't load file %s",
|
||||
args[0]);
|
||||
out:
|
||||
grub_free (cutargs);
|
||||
return err;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_legacy_initrd (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
struct grub_command *cmd;
|
||||
|
||||
if (kernel_type == LINUX)
|
||||
{
|
||||
#ifdef GRUB_MACHINE_PCBIOS
|
||||
cmd = grub_command_find ("initrd16");
|
||||
#else
|
||||
cmd = grub_command_find ("initrd");
|
||||
#endif
|
||||
if (!cmd)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"),
|
||||
#ifdef GRUB_MACHINE_PCBIOS
|
||||
"initrd16"
|
||||
#else
|
||||
"initrd"
|
||||
#endif
|
||||
);
|
||||
|
||||
return cmd->func (cmd, argc ? 1 : 0, args);
|
||||
}
|
||||
if (kernel_type == MULTIBOOT)
|
||||
{
|
||||
cmd = grub_command_find ("module");
|
||||
if (!cmd)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"),
|
||||
"module");
|
||||
|
||||
return cmd->func (cmd, argc, args);
|
||||
}
|
||||
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
N_("you need to load the kernel first"));
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_legacy_initrdnounzip (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
struct grub_command *cmd;
|
||||
|
||||
if (kernel_type == LINUX)
|
||||
{
|
||||
cmd = grub_command_find ("initrd16");
|
||||
if (!cmd)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"),
|
||||
"initrd16");
|
||||
|
||||
return cmd->func (cmd, argc, args);
|
||||
}
|
||||
if (kernel_type == MULTIBOOT)
|
||||
{
|
||||
char **newargs;
|
||||
grub_err_t err;
|
||||
char nounzipbuf[10] = "--nounzip";
|
||||
|
||||
cmd = grub_command_find ("module");
|
||||
if (!cmd)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"),
|
||||
"module");
|
||||
|
||||
newargs = grub_malloc ((argc + 1) * sizeof (newargs[0]));
|
||||
if (!newargs)
|
||||
return grub_errno;
|
||||
grub_memcpy (newargs + 1, args, argc * sizeof (newargs[0]));
|
||||
newargs[0] = nounzipbuf;
|
||||
|
||||
err = cmd->func (cmd, argc + 1, newargs);
|
||||
grub_free (newargs);
|
||||
return err;
|
||||
}
|
||||
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
N_("you need to load the kernel first"));
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
check_password_deny (const char *user __attribute__ ((unused)),
|
||||
const char *entered __attribute__ ((unused)),
|
||||
void *password __attribute__ ((unused)))
|
||||
{
|
||||
return GRUB_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
#define MD5_HASHLEN 16
|
||||
|
||||
struct legacy_md5_password
|
||||
{
|
||||
grub_uint8_t *salt;
|
||||
int saltlen;
|
||||
grub_uint8_t hash[MD5_HASHLEN];
|
||||
};
|
||||
|
||||
static int
|
||||
check_password_md5_real (const char *entered,
|
||||
struct legacy_md5_password *pw)
|
||||
{
|
||||
grub_size_t enteredlen = grub_strlen (entered);
|
||||
unsigned char alt_result[MD5_HASHLEN];
|
||||
unsigned char *digest;
|
||||
grub_uint8_t *ctx;
|
||||
grub_size_t i;
|
||||
int ret;
|
||||
|
||||
ctx = grub_zalloc (GRUB_MD_MD5->contextsize);
|
||||
if (!ctx)
|
||||
return 0;
|
||||
|
||||
GRUB_MD_MD5->init (ctx);
|
||||
GRUB_MD_MD5->write (ctx, entered, enteredlen);
|
||||
GRUB_MD_MD5->write (ctx, pw->salt + 3, pw->saltlen - 3);
|
||||
GRUB_MD_MD5->write (ctx, entered, enteredlen);
|
||||
digest = GRUB_MD_MD5->read (ctx);
|
||||
GRUB_MD_MD5->final (ctx);
|
||||
grub_memcpy (alt_result, digest, MD5_HASHLEN);
|
||||
|
||||
GRUB_MD_MD5->init (ctx);
|
||||
GRUB_MD_MD5->write (ctx, entered, enteredlen);
|
||||
GRUB_MD_MD5->write (ctx, pw->salt, pw->saltlen); /* include the $1$ header */
|
||||
for (i = enteredlen; i > 16; i -= 16)
|
||||
GRUB_MD_MD5->write (ctx, alt_result, 16);
|
||||
GRUB_MD_MD5->write (ctx, alt_result, i);
|
||||
|
||||
for (i = enteredlen; i > 0; i >>= 1)
|
||||
GRUB_MD_MD5->write (ctx, entered + ((i & 1) ? enteredlen : 0), 1);
|
||||
digest = GRUB_MD_MD5->read (ctx);
|
||||
GRUB_MD_MD5->final (ctx);
|
||||
|
||||
for (i = 0; i < 1000; i++)
|
||||
{
|
||||
grub_memcpy (alt_result, digest, 16);
|
||||
|
||||
GRUB_MD_MD5->init (ctx);
|
||||
if ((i & 1) != 0)
|
||||
GRUB_MD_MD5->write (ctx, entered, enteredlen);
|
||||
else
|
||||
GRUB_MD_MD5->write (ctx, alt_result, 16);
|
||||
|
||||
if (i % 3 != 0)
|
||||
GRUB_MD_MD5->write (ctx, pw->salt + 3, pw->saltlen - 3);
|
||||
|
||||
if (i % 7 != 0)
|
||||
GRUB_MD_MD5->write (ctx, entered, enteredlen);
|
||||
|
||||
if ((i & 1) != 0)
|
||||
GRUB_MD_MD5->write (ctx, alt_result, 16);
|
||||
else
|
||||
GRUB_MD_MD5->write (ctx, entered, enteredlen);
|
||||
digest = GRUB_MD_MD5->read (ctx);
|
||||
GRUB_MD_MD5->final (ctx);
|
||||
}
|
||||
|
||||
ret = (grub_crypto_memcmp (digest, pw->hash, MD5_HASHLEN) == 0);
|
||||
grub_free (ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
check_password_md5 (const char *user,
|
||||
const char *entered,
|
||||
void *password)
|
||||
{
|
||||
if (!check_password_md5_real (entered, password))
|
||||
return GRUB_ACCESS_DENIED;
|
||||
|
||||
grub_auth_authenticate (user);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static inline int
|
||||
ib64t (char c)
|
||||
{
|
||||
if (c == '.')
|
||||
return 0;
|
||||
if (c == '/')
|
||||
return 1;
|
||||
if (c >= '0' && c <= '9')
|
||||
return c - '0' + 2;
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
return c - 'A' + 12;
|
||||
if (c >= 'a' && c <= 'z')
|
||||
return c - 'a' + 38;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static struct legacy_md5_password *
|
||||
parse_legacy_md5 (int argc, char **args)
|
||||
{
|
||||
const char *salt, *saltend;
|
||||
struct legacy_md5_password *pw = NULL;
|
||||
int i;
|
||||
const char *p;
|
||||
|
||||
if (grub_memcmp (args[0], "--md5", sizeof ("--md5")) != 0)
|
||||
goto fail;
|
||||
if (argc == 1)
|
||||
goto fail;
|
||||
if (grub_strlen(args[1]) <= 3)
|
||||
goto fail;
|
||||
salt = args[1];
|
||||
saltend = grub_strchr (salt + 3, '$');
|
||||
if (!saltend)
|
||||
goto fail;
|
||||
pw = grub_malloc (sizeof (*pw));
|
||||
if (!pw)
|
||||
goto fail;
|
||||
|
||||
p = saltend + 1;
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
int n;
|
||||
grub_uint32_t w = 0;
|
||||
|
||||
for (n = 0; n < 4; n++)
|
||||
{
|
||||
int ww = ib64t(*p++);
|
||||
if (ww == -1)
|
||||
goto fail;
|
||||
w |= ww << (n * 6);
|
||||
}
|
||||
pw->hash[i == 4 ? 5 : 12+i] = w & 0xff;
|
||||
pw->hash[6+i] = (w >> 8) & 0xff;
|
||||
pw->hash[i] = (w >> 16) & 0xff;
|
||||
}
|
||||
{
|
||||
int n;
|
||||
grub_uint32_t w = 0;
|
||||
for (n = 0; n < 2; n++)
|
||||
{
|
||||
int ww = ib64t(*p++);
|
||||
if (ww == -1)
|
||||
goto fail;
|
||||
w |= ww << (6 * n);
|
||||
}
|
||||
if (w >= 0x100)
|
||||
goto fail;
|
||||
pw->hash[11] = w;
|
||||
}
|
||||
|
||||
pw->saltlen = saltend - salt;
|
||||
pw->salt = (grub_uint8_t *) grub_strndup (salt, pw->saltlen);
|
||||
if (!pw->salt)
|
||||
goto fail;
|
||||
|
||||
return pw;
|
||||
|
||||
fail:
|
||||
grub_free (pw);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_legacy_password (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
struct legacy_md5_password *pw = NULL;
|
||||
|
||||
if (argc == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
|
||||
if (args[0][0] != '-' || args[0][1] != '-')
|
||||
return grub_normal_set_password ("legacy", args[0]);
|
||||
|
||||
pw = parse_legacy_md5 (argc, args);
|
||||
|
||||
if (pw)
|
||||
return grub_auth_register_authentication ("legacy", check_password_md5, pw);
|
||||
else
|
||||
/* This is to imitate minor difference between grub-legacy in GRUB2.
|
||||
If 2 password commands are executed in a row and second one fails
|
||||
on GRUB2 the password of first one is used, whereas in grub-legacy
|
||||
authenthication is denied. In case of no password command was executed
|
||||
early both versions deny any access. */
|
||||
return grub_auth_register_authentication ("legacy", check_password_deny,
|
||||
NULL);
|
||||
}
|
||||
|
||||
int
|
||||
grub_legacy_check_md5_password (int argc, char **args,
|
||||
char *entered)
|
||||
{
|
||||
struct legacy_md5_password *pw = NULL;
|
||||
int ret;
|
||||
|
||||
if (args[0][0] != '-' || args[0][1] != '-')
|
||||
{
|
||||
char correct[GRUB_AUTH_MAX_PASSLEN];
|
||||
|
||||
grub_memset (correct, 0, sizeof (correct));
|
||||
grub_strncpy (correct, args[0], sizeof (correct));
|
||||
|
||||
return grub_crypto_memcmp (entered, correct, GRUB_AUTH_MAX_PASSLEN) == 0;
|
||||
}
|
||||
|
||||
pw = parse_legacy_md5 (argc, args);
|
||||
|
||||
if (!pw)
|
||||
return 0;
|
||||
|
||||
ret = check_password_md5_real (entered, pw);
|
||||
grub_free (pw);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_legacy_check_password (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
char entered[GRUB_AUTH_MAX_PASSLEN];
|
||||
|
||||
if (argc == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
|
||||
grub_puts_ (N_("Enter password: "));
|
||||
if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN))
|
||||
return GRUB_ACCESS_DENIED;
|
||||
|
||||
if (!grub_legacy_check_md5_password (argc, args,
|
||||
entered))
|
||||
return GRUB_ACCESS_DENIED;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_command_t cmd_source, cmd_configfile;
|
||||
static grub_command_t cmd_source_extract, cmd_configfile_extract;
|
||||
static grub_command_t cmd_kernel, cmd_initrd, cmd_initrdnounzip;
|
||||
static grub_command_t cmd_password, cmd_check_password;
|
||||
|
||||
GRUB_MOD_INIT(legacycfg)
|
||||
{
|
||||
cmd_source
|
||||
= grub_register_command ("legacy_source",
|
||||
grub_cmd_legacy_source,
|
||||
N_("FILE"),
|
||||
/* TRANSLATORS: "legacy config" means
|
||||
"config as used by grub-legacy". */
|
||||
N_("Parse legacy config in same context"));
|
||||
cmd_configfile
|
||||
= grub_register_command ("legacy_configfile",
|
||||
grub_cmd_legacy_source,
|
||||
N_("FILE"),
|
||||
N_("Parse legacy config in new context"));
|
||||
cmd_source_extract
|
||||
= grub_register_command ("extract_legacy_entries_source",
|
||||
grub_cmd_legacy_source,
|
||||
N_("FILE"),
|
||||
N_("Parse legacy config in same context taking only menu entries"));
|
||||
cmd_configfile_extract
|
||||
= grub_register_command ("extract_legacy_entries_configfile",
|
||||
grub_cmd_legacy_source,
|
||||
N_("FILE"),
|
||||
N_("Parse legacy config in new context taking only menu entries"));
|
||||
|
||||
cmd_kernel = grub_register_command ("legacy_kernel",
|
||||
grub_cmd_legacy_kernel,
|
||||
N_("[--no-mem-option] [--type=TYPE] FILE [ARG ...]"),
|
||||
N_("Simulate grub-legacy `kernel' command"));
|
||||
|
||||
cmd_initrd = grub_register_command ("legacy_initrd",
|
||||
grub_cmd_legacy_initrd,
|
||||
N_("FILE [ARG ...]"),
|
||||
N_("Simulate grub-legacy `initrd' command"));
|
||||
cmd_initrdnounzip = grub_register_command ("legacy_initrd_nounzip",
|
||||
grub_cmd_legacy_initrdnounzip,
|
||||
N_("FILE [ARG ...]"),
|
||||
N_("Simulate grub-legacy `modulenounzip' command"));
|
||||
|
||||
cmd_password = grub_register_command ("legacy_password",
|
||||
grub_cmd_legacy_password,
|
||||
N_("[--md5] PASSWD [FILE]"),
|
||||
N_("Simulate grub-legacy `password' command"));
|
||||
|
||||
cmd_check_password = grub_register_command ("legacy_check_password",
|
||||
grub_cmd_legacy_check_password,
|
||||
N_("[--md5] PASSWD [FILE]"),
|
||||
N_("Simulate grub-legacy `password' command in menu entry mode"));
|
||||
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(legacycfg)
|
||||
{
|
||||
grub_unregister_command (cmd_source);
|
||||
grub_unregister_command (cmd_configfile);
|
||||
grub_unregister_command (cmd_source_extract);
|
||||
grub_unregister_command (cmd_configfile_extract);
|
||||
|
||||
grub_unregister_command (cmd_kernel);
|
||||
grub_unregister_command (cmd_initrd);
|
||||
grub_unregister_command (cmd_initrdnounzip);
|
||||
|
||||
grub_unregister_command (cmd_password);
|
||||
grub_unregister_command (cmd_check_password);
|
||||
}
|
397
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/loadenv.c
Normal file
@@ -0,0 +1,397 @@
|
||||
/* loadenv.c - command to load/save environment variable. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008,2009,2010 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/dl.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/partition.h>
|
||||
#include <grub/lib/envblk.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
#include "loadenv.h"
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
/* TRANSLATORS: This option is used to override default filename
|
||||
for loading and storing environment. */
|
||||
{"file", 'f', 0, N_("Specify filename."), 0, ARG_TYPE_PATHNAME},
|
||||
{"skip-sig", 's', 0,
|
||||
N_("Skip signature-checking of the environment file."), 0, ARG_TYPE_NONE},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
/* Opens 'filename' with compression filters disabled. Optionally disables the
|
||||
PUBKEY filter (that insists upon properly signed files) as well. PUBKEY
|
||||
filter is restored before the function returns. */
|
||||
static grub_file_t
|
||||
open_envblk_file (char *filename,
|
||||
enum grub_file_type type)
|
||||
{
|
||||
grub_file_t file;
|
||||
char *buf = 0;
|
||||
|
||||
if (! filename)
|
||||
{
|
||||
const char *prefix;
|
||||
int len;
|
||||
|
||||
prefix = grub_env_get ("prefix");
|
||||
if (! prefix)
|
||||
{
|
||||
grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "prefix");
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = grub_strlen (prefix);
|
||||
buf = grub_malloc (len + 1 + sizeof (GRUB_ENVBLK_DEFCFG));
|
||||
if (! buf)
|
||||
return 0;
|
||||
filename = buf;
|
||||
|
||||
grub_strcpy (filename, prefix);
|
||||
filename[len] = '/';
|
||||
grub_strcpy (filename + len + 1, GRUB_ENVBLK_DEFCFG);
|
||||
}
|
||||
|
||||
file = grub_file_open (filename, type);
|
||||
|
||||
grub_free (buf);
|
||||
return file;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_load_env (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
grub_file_t file;
|
||||
grub_envblk_t envblk;
|
||||
grub_env_whitelist_t whitelist;
|
||||
|
||||
whitelist.len = argc;
|
||||
whitelist.list = args;
|
||||
|
||||
/* state[0] is the -f flag; state[1] is the --skip-sig flag */
|
||||
file = open_envblk_file ((state[0].set) ? state[0].arg : 0,
|
||||
GRUB_FILE_TYPE_LOADENV
|
||||
| (state[1].set
|
||||
? GRUB_FILE_TYPE_SKIP_SIGNATURE : GRUB_FILE_TYPE_NONE));
|
||||
if (! file)
|
||||
return grub_errno;
|
||||
|
||||
envblk = read_envblk_file (file);
|
||||
if (! envblk)
|
||||
goto fail;
|
||||
|
||||
/* argc > 0 indicates caller provided a whitelist of variables to read. */
|
||||
grub_envblk_iterate (envblk, argc > 0 ? &whitelist : 0, set_var);
|
||||
grub_envblk_close (envblk);
|
||||
|
||||
fail:
|
||||
grub_file_close (file);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
/* Print all variables in current context. */
|
||||
static int
|
||||
print_var (const char *name, const char *value,
|
||||
void *hook_data __attribute__ ((unused)))
|
||||
{
|
||||
grub_printf ("%s=%s\n", name, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_list_env (grub_extcmd_context_t ctxt,
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
grub_file_t file;
|
||||
grub_envblk_t envblk;
|
||||
|
||||
file = open_envblk_file ((state[0].set) ? state[0].arg : 0,
|
||||
GRUB_FILE_TYPE_LOADENV
|
||||
| (state[1].set
|
||||
? GRUB_FILE_TYPE_SKIP_SIGNATURE : GRUB_FILE_TYPE_NONE));
|
||||
if (! file)
|
||||
return grub_errno;
|
||||
|
||||
envblk = read_envblk_file (file);
|
||||
if (! envblk)
|
||||
goto fail;
|
||||
|
||||
grub_envblk_iterate (envblk, NULL, print_var);
|
||||
grub_envblk_close (envblk);
|
||||
|
||||
fail:
|
||||
grub_file_close (file);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
/* Used to maintain a variable length of blocklists internally. */
|
||||
struct blocklist
|
||||
{
|
||||
grub_disk_addr_t sector;
|
||||
unsigned offset;
|
||||
unsigned length;
|
||||
struct blocklist *next;
|
||||
};
|
||||
|
||||
static void
|
||||
free_blocklists (struct blocklist *p)
|
||||
{
|
||||
struct blocklist *q;
|
||||
|
||||
for (; p; p = q)
|
||||
{
|
||||
q = p->next;
|
||||
grub_free (p);
|
||||
}
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
check_blocklists (grub_envblk_t envblk, struct blocklist *blocklists,
|
||||
grub_file_t file)
|
||||
{
|
||||
grub_size_t total_length;
|
||||
grub_size_t index;
|
||||
grub_disk_t disk;
|
||||
grub_disk_addr_t part_start;
|
||||
struct blocklist *p;
|
||||
char *buf;
|
||||
|
||||
/* Sanity checks. */
|
||||
total_length = 0;
|
||||
for (p = blocklists; p; p = p->next)
|
||||
{
|
||||
struct blocklist *q;
|
||||
/* Check if any pair of blocks overlap. */
|
||||
for (q = p->next; q; q = q->next)
|
||||
{
|
||||
grub_disk_addr_t s1, s2;
|
||||
grub_disk_addr_t e1, e2;
|
||||
|
||||
s1 = p->sector;
|
||||
e1 = s1 + ((p->length + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS);
|
||||
|
||||
s2 = q->sector;
|
||||
e2 = s2 + ((q->length + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS);
|
||||
|
||||
if (s1 < e2 && s2 < e1)
|
||||
{
|
||||
/* This might be actually valid, but it is unbelievable that
|
||||
any filesystem makes such a silly allocation. */
|
||||
return grub_error (GRUB_ERR_BAD_FS, "malformed file");
|
||||
}
|
||||
}
|
||||
|
||||
total_length += p->length;
|
||||
}
|
||||
|
||||
if (total_length != grub_file_size (file))
|
||||
{
|
||||
/* Maybe sparse, unallocated sectors. No way in GRUB. */
|
||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "sparse file not allowed");
|
||||
}
|
||||
|
||||
/* One more sanity check. Re-read all sectors by blocklists, and compare
|
||||
those with the data read via a file. */
|
||||
disk = file->device->disk;
|
||||
|
||||
part_start = grub_partition_get_start (disk->partition);
|
||||
|
||||
buf = grub_envblk_buffer (envblk);
|
||||
char *blockbuf = NULL;
|
||||
grub_size_t blockbuf_len = 0;
|
||||
for (p = blocklists, index = 0; p; index += p->length, p = p->next)
|
||||
{
|
||||
if (p->length > blockbuf_len)
|
||||
{
|
||||
grub_free (blockbuf);
|
||||
blockbuf_len = 2 * p->length;
|
||||
blockbuf = grub_malloc (blockbuf_len);
|
||||
if (!blockbuf)
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
if (grub_disk_read (disk, p->sector - part_start,
|
||||
p->offset, p->length, blockbuf))
|
||||
return grub_errno;
|
||||
|
||||
if (grub_memcmp (buf + index, blockbuf, p->length) != 0)
|
||||
return grub_error (GRUB_ERR_FILE_READ_ERROR, "invalid blocklist");
|
||||
}
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static int
|
||||
write_blocklists (grub_envblk_t envblk, struct blocklist *blocklists,
|
||||
grub_file_t file)
|
||||
{
|
||||
char *buf;
|
||||
grub_disk_t disk;
|
||||
grub_disk_addr_t part_start;
|
||||
struct blocklist *p;
|
||||
grub_size_t index;
|
||||
|
||||
buf = grub_envblk_buffer (envblk);
|
||||
disk = file->device->disk;
|
||||
part_start = grub_partition_get_start (disk->partition);
|
||||
|
||||
index = 0;
|
||||
for (p = blocklists; p; index += p->length, p = p->next)
|
||||
{
|
||||
if (grub_disk_write (disk, p->sector - part_start,
|
||||
p->offset, p->length, buf + index))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Context for grub_cmd_save_env. */
|
||||
struct grub_cmd_save_env_ctx
|
||||
{
|
||||
struct blocklist *head, *tail;
|
||||
};
|
||||
|
||||
/* Store blocklists in a linked list. */
|
||||
static void
|
||||
save_env_read_hook (grub_disk_addr_t sector, unsigned offset, unsigned length,
|
||||
void *data)
|
||||
{
|
||||
struct grub_cmd_save_env_ctx *ctx = data;
|
||||
struct blocklist *block;
|
||||
|
||||
block = grub_malloc (sizeof (*block));
|
||||
if (! block)
|
||||
return;
|
||||
|
||||
block->sector = sector;
|
||||
block->offset = offset;
|
||||
block->length = length;
|
||||
|
||||
/* Slightly complicated, because the list should be FIFO. */
|
||||
block->next = 0;
|
||||
if (ctx->tail)
|
||||
ctx->tail->next = block;
|
||||
ctx->tail = block;
|
||||
if (! ctx->head)
|
||||
ctx->head = block;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_save_env (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
grub_file_t file;
|
||||
grub_envblk_t envblk;
|
||||
struct grub_cmd_save_env_ctx ctx = {
|
||||
.head = 0,
|
||||
.tail = 0
|
||||
};
|
||||
|
||||
if (! argc)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no variable is specified");
|
||||
|
||||
file = open_envblk_file ((state[0].set) ? state[0].arg : 0,
|
||||
GRUB_FILE_TYPE_SAVEENV
|
||||
| GRUB_FILE_TYPE_SKIP_SIGNATURE);
|
||||
if (! file)
|
||||
return grub_errno;
|
||||
|
||||
if (! file->device->disk)
|
||||
{
|
||||
grub_file_close (file);
|
||||
return grub_error (GRUB_ERR_BAD_DEVICE, "disk device required");
|
||||
}
|
||||
|
||||
file->read_hook = save_env_read_hook;
|
||||
file->read_hook_data = &ctx;
|
||||
envblk = read_envblk_file (file);
|
||||
file->read_hook = 0;
|
||||
if (! envblk)
|
||||
goto fail;
|
||||
|
||||
if (check_blocklists (envblk, ctx.head, file))
|
||||
goto fail;
|
||||
|
||||
while (argc)
|
||||
{
|
||||
const char *value;
|
||||
|
||||
value = grub_env_get (args[0]);
|
||||
if (value)
|
||||
{
|
||||
if (! grub_envblk_set (envblk, args[0], value))
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "environment block too small");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else
|
||||
grub_envblk_delete (envblk, args[0]);
|
||||
|
||||
argc--;
|
||||
args++;
|
||||
}
|
||||
|
||||
write_blocklists (envblk, ctx.head, file);
|
||||
|
||||
fail:
|
||||
if (envblk)
|
||||
grub_envblk_close (envblk);
|
||||
free_blocklists (ctx.head);
|
||||
grub_file_close (file);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd_load, cmd_list, cmd_save;
|
||||
|
||||
GRUB_MOD_INIT(loadenv)
|
||||
{
|
||||
cmd_load =
|
||||
grub_register_extcmd ("load_env", grub_cmd_load_env, 0,
|
||||
N_("[-f FILE] [-s|--skip-sig] [variable_name_to_whitelist] [...]"),
|
||||
N_("Load variables from environment block file."),
|
||||
options);
|
||||
cmd_list =
|
||||
grub_register_extcmd ("list_env", grub_cmd_list_env, 0, N_("[-f FILE]"),
|
||||
N_("List variables from environment block file."),
|
||||
options);
|
||||
cmd_save =
|
||||
grub_register_extcmd ("save_env", grub_cmd_save_env, 0,
|
||||
N_("[-f FILE] variable_name [...]"),
|
||||
N_("Save variables to environment block file."),
|
||||
options);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(loadenv)
|
||||
{
|
||||
grub_unregister_extcmd (cmd_load);
|
||||
grub_unregister_extcmd (cmd_list);
|
||||
grub_unregister_extcmd (cmd_save);
|
||||
}
|
93
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/loadenv.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/* loadenv.c - command to load/save environment variable. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008,2009,2010 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
static grub_envblk_t UNUSED
|
||||
read_envblk_file (grub_file_t file)
|
||||
{
|
||||
grub_off_t offset = 0;
|
||||
char *buf;
|
||||
grub_size_t size = grub_file_size (file);
|
||||
grub_envblk_t envblk;
|
||||
|
||||
buf = grub_malloc (size);
|
||||
if (! buf)
|
||||
return 0;
|
||||
|
||||
while (size > 0)
|
||||
{
|
||||
grub_ssize_t ret;
|
||||
|
||||
ret = grub_file_read (file, buf + offset, size);
|
||||
if (ret <= 0)
|
||||
{
|
||||
grub_free (buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size -= ret;
|
||||
offset += ret;
|
||||
}
|
||||
|
||||
envblk = grub_envblk_open (buf, offset);
|
||||
if (! envblk)
|
||||
{
|
||||
grub_free (buf);
|
||||
grub_error (GRUB_ERR_BAD_FILE_TYPE, "invalid environment block");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return envblk;
|
||||
}
|
||||
|
||||
struct grub_env_whitelist
|
||||
{
|
||||
grub_size_t len;
|
||||
char **list;
|
||||
};
|
||||
typedef struct grub_env_whitelist grub_env_whitelist_t;
|
||||
|
||||
static int UNUSED
|
||||
test_whitelist_membership (const char* name,
|
||||
const grub_env_whitelist_t* whitelist)
|
||||
{
|
||||
grub_size_t i;
|
||||
|
||||
for (i = 0; i < whitelist->len; i++)
|
||||
if (grub_strcmp (name, whitelist->list[i]) == 0)
|
||||
return 1; /* found it */
|
||||
|
||||
return 0; /* not found */
|
||||
}
|
||||
|
||||
/* Helper for grub_cmd_load_env. */
|
||||
static int UNUSED
|
||||
set_var (const char *name, const char *value, void *whitelist)
|
||||
{
|
||||
if (! whitelist)
|
||||
{
|
||||
grub_env_set (name, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (test_whitelist_membership (name,
|
||||
(const grub_env_whitelist_t *) whitelist))
|
||||
grub_env_set (name, value);
|
||||
|
||||
return 0;
|
||||
}
|
349
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/menuentry.c
Normal file
@@ -0,0 +1,349 @@
|
||||
/* menuentry.c - menuentry command */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/types.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/normal.h>
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{"class", 1, GRUB_ARG_OPTION_REPEATABLE,
|
||||
N_("Menu entry type."), N_("STRING"), ARG_TYPE_STRING},
|
||||
{"users", 2, 0,
|
||||
N_("List of users allowed to boot this entry."), N_("USERNAME[,USERNAME]"),
|
||||
ARG_TYPE_STRING},
|
||||
{"hotkey", 3, 0,
|
||||
N_("Keyboard key to quickly boot this entry."), N_("KEYBOARD_KEY"), ARG_TYPE_STRING},
|
||||
{"source", 4, 0,
|
||||
N_("Use STRING as menu entry body."), N_("STRING"), ARG_TYPE_STRING},
|
||||
{"id", 0, 0, N_("Menu entry identifier."), N_("STRING"), ARG_TYPE_STRING},
|
||||
/* TRANSLATORS: menu entry can either be bootable by anyone or only by
|
||||
handful of users. By default when security is active only superusers can
|
||||
boot a given menu entry. With --unrestricted (this option)
|
||||
anyone can boot it. */
|
||||
{"unrestricted", 0, 0, N_("This entry can be booted by any user."),
|
||||
0, ARG_TYPE_NONE},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static struct
|
||||
{
|
||||
const char *name;
|
||||
int key;
|
||||
} hotkey_aliases[] =
|
||||
{
|
||||
{"backspace", GRUB_TERM_BACKSPACE},
|
||||
{"tab", GRUB_TERM_TAB},
|
||||
{"delete", GRUB_TERM_KEY_DC},
|
||||
{"insert", GRUB_TERM_KEY_INSERT},
|
||||
{"f1", GRUB_TERM_KEY_F1},
|
||||
{"f2", GRUB_TERM_KEY_F2},
|
||||
{"f3", GRUB_TERM_KEY_F3},
|
||||
{"f4", GRUB_TERM_KEY_F4},
|
||||
{"f5", GRUB_TERM_KEY_F5},
|
||||
{"f6", GRUB_TERM_KEY_F6},
|
||||
{"f7", GRUB_TERM_KEY_F7},
|
||||
{"f8", GRUB_TERM_KEY_F8},
|
||||
{"f9", GRUB_TERM_KEY_F9},
|
||||
{"f10", GRUB_TERM_KEY_F10},
|
||||
{"f11", GRUB_TERM_KEY_F11},
|
||||
{"f12", GRUB_TERM_KEY_F12},
|
||||
};
|
||||
|
||||
/* Add a menu entry to the current menu context (as given by the environment
|
||||
variable data slot `menu'). As the configuration file is read, the script
|
||||
parser calls this when a menu entry is to be created. */
|
||||
grub_err_t
|
||||
grub_normal_add_menu_entry (int argc, const char **args,
|
||||
char **classes, const char *id,
|
||||
const char *users, const char *hotkey,
|
||||
const char *prefix, const char *sourcecode,
|
||||
int submenu, int *index, struct bls_entry *bls)
|
||||
{
|
||||
int menu_hotkey = 0;
|
||||
char **menu_args = NULL;
|
||||
char *menu_users = NULL;
|
||||
char *menu_title = NULL;
|
||||
char *menu_sourcecode = NULL;
|
||||
char *menu_id = NULL;
|
||||
struct grub_menu_entry_class *menu_classes = NULL;
|
||||
|
||||
grub_menu_t menu;
|
||||
grub_menu_entry_t *last;
|
||||
|
||||
menu = grub_env_get_menu ();
|
||||
if (! menu)
|
||||
return grub_error (GRUB_ERR_MENU, "no menu context");
|
||||
|
||||
last = &menu->entry_list;
|
||||
|
||||
menu_sourcecode = grub_xasprintf ("%s%s", prefix ?: "", sourcecode);
|
||||
if (! menu_sourcecode)
|
||||
return grub_errno;
|
||||
|
||||
if (classes && classes[0])
|
||||
{
|
||||
int i;
|
||||
for (i = 0; classes[i]; i++); /* count # of menuentry classes */
|
||||
menu_classes = grub_zalloc (sizeof (struct grub_menu_entry_class)
|
||||
* (i + 1));
|
||||
if (! menu_classes)
|
||||
goto fail;
|
||||
|
||||
for (i = 0; classes[i]; i++)
|
||||
{
|
||||
menu_classes[i].name = grub_strdup (classes[i]);
|
||||
if (! menu_classes[i].name)
|
||||
goto fail;
|
||||
menu_classes[i].next = classes[i + 1] ? &menu_classes[i + 1] : NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (users)
|
||||
{
|
||||
menu_users = grub_strdup (users);
|
||||
if (! menu_users)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (hotkey)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < ARRAY_SIZE (hotkey_aliases); i++)
|
||||
if (grub_strcmp (hotkey, hotkey_aliases[i].name) == 0)
|
||||
{
|
||||
menu_hotkey = hotkey_aliases[i].key;
|
||||
break;
|
||||
}
|
||||
if (i == ARRAY_SIZE (hotkey_aliases))
|
||||
menu_hotkey = hotkey[0];
|
||||
}
|
||||
|
||||
if (! argc)
|
||||
{
|
||||
grub_error (GRUB_ERR_MENU, "menuentry is missing title");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
menu_title = grub_strdup (args[0]);
|
||||
if (! menu_title)
|
||||
goto fail;
|
||||
|
||||
grub_dprintf ("menu", "id:\"%s\"\n", id);
|
||||
grub_dprintf ("menu", "title:\"%s\"\n", menu_title);
|
||||
menu_id = grub_strdup (id ? : menu_title);
|
||||
if (! menu_id)
|
||||
goto fail;
|
||||
grub_dprintf ("menu", "menu_id:\"%s\"\n", menu_id);
|
||||
|
||||
/* Save argc, args to pass as parameters to block arg later. */
|
||||
menu_args = grub_malloc (sizeof (char*) * (argc + 1));
|
||||
if (! menu_args)
|
||||
goto fail;
|
||||
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
menu_args[i] = grub_strdup (args[i]);
|
||||
if (! menu_args[i])
|
||||
goto fail;
|
||||
}
|
||||
menu_args[argc] = NULL;
|
||||
}
|
||||
|
||||
/* Add the menu entry at the end of the list. */
|
||||
int ind=0;
|
||||
while (*last)
|
||||
{
|
||||
ind++;
|
||||
last = &(*last)->next;
|
||||
}
|
||||
|
||||
*last = grub_zalloc (sizeof (**last));
|
||||
if (! *last)
|
||||
goto fail;
|
||||
|
||||
(*last)->title = menu_title;
|
||||
(*last)->id = menu_id;
|
||||
(*last)->hotkey = menu_hotkey;
|
||||
(*last)->classes = menu_classes;
|
||||
if (menu_users)
|
||||
(*last)->restricted = 1;
|
||||
(*last)->users = menu_users;
|
||||
(*last)->argc = argc;
|
||||
(*last)->args = menu_args;
|
||||
(*last)->sourcecode = menu_sourcecode;
|
||||
(*last)->submenu = submenu;
|
||||
(*last)->bls = bls;
|
||||
|
||||
menu->size++;
|
||||
if (index)
|
||||
*index = ind;
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
fail:
|
||||
|
||||
grub_free (menu_sourcecode);
|
||||
{
|
||||
int i;
|
||||
for (i = 0; menu_classes && menu_classes[i].name; i++)
|
||||
grub_free (menu_classes[i].name);
|
||||
grub_free (menu_classes);
|
||||
}
|
||||
|
||||
{
|
||||
int i;
|
||||
for (i = 0; menu_args && menu_args[i]; i++)
|
||||
grub_free (menu_args[i]);
|
||||
grub_free (menu_args);
|
||||
}
|
||||
|
||||
grub_free (menu_users);
|
||||
grub_free (menu_title);
|
||||
grub_free (menu_id);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static char *
|
||||
setparams_prefix (int argc, char **args)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
char *p;
|
||||
char *result;
|
||||
grub_size_t len = 10;
|
||||
|
||||
/* Count resulting string length */
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
len += 3; /* 3 = 1 space + 2 quotes */
|
||||
p = args[i];
|
||||
while (*p)
|
||||
len += (*p++ == '\'' ? 3 : 1);
|
||||
}
|
||||
|
||||
result = grub_malloc (len + 2);
|
||||
if (! result)
|
||||
return 0;
|
||||
|
||||
grub_strcpy (result, "setparams");
|
||||
p = result + 9;
|
||||
|
||||
for (j = 0; j < argc; j++)
|
||||
{
|
||||
*p++ = ' ';
|
||||
*p++ = '\'';
|
||||
p = grub_strchrsub (p, args[j], '\'', "'\\''");
|
||||
*p++ = '\'';
|
||||
}
|
||||
*p++ = '\n';
|
||||
*p = '\0';
|
||||
return result;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
char ch;
|
||||
char *src;
|
||||
char *prefix;
|
||||
unsigned len;
|
||||
grub_err_t r;
|
||||
const char *users;
|
||||
|
||||
if (! argc)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing arguments");
|
||||
|
||||
if (ctxt->state[3].set && ctxt->script)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "multiple menuentry definitions");
|
||||
|
||||
if (! ctxt->state[3].set && ! ctxt->script)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no menuentry definition");
|
||||
|
||||
if (ctxt->state[1].set)
|
||||
users = ctxt->state[1].arg;
|
||||
else if (ctxt->state[5].set)
|
||||
users = NULL;
|
||||
else
|
||||
users = "";
|
||||
|
||||
if (! ctxt->script)
|
||||
return grub_normal_add_menu_entry (argc, (const char **) args,
|
||||
(ctxt->state[0].set ? ctxt->state[0].args
|
||||
: NULL),
|
||||
ctxt->state[4].arg,
|
||||
users,
|
||||
ctxt->state[2].arg, 0,
|
||||
ctxt->state[3].arg,
|
||||
ctxt->extcmd->cmd->name[0] == 's',
|
||||
NULL, NULL);
|
||||
|
||||
src = args[argc - 1];
|
||||
args[argc - 1] = NULL;
|
||||
|
||||
len = grub_strlen(src);
|
||||
ch = src[len - 1];
|
||||
src[len - 1] = '\0';
|
||||
|
||||
prefix = setparams_prefix (argc - 1, args);
|
||||
if (! prefix)
|
||||
return grub_errno;
|
||||
|
||||
r = grub_normal_add_menu_entry (argc - 1, (const char **) args,
|
||||
ctxt->state[0].args, ctxt->state[4].arg,
|
||||
users,
|
||||
ctxt->state[2].arg, prefix, src + 1,
|
||||
ctxt->extcmd->cmd->name[0] == 's', NULL,
|
||||
NULL);
|
||||
|
||||
src[len - 1] = ch;
|
||||
args[argc - 1] = src;
|
||||
grub_free (prefix);
|
||||
return r;
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd, cmd_sub;
|
||||
|
||||
void
|
||||
grub_menu_init (void)
|
||||
{
|
||||
cmd = grub_register_extcmd ("menuentry", grub_cmd_menuentry,
|
||||
GRUB_COMMAND_FLAG_BLOCKS
|
||||
| GRUB_COMMAND_ACCEPT_DASH
|
||||
| GRUB_COMMAND_FLAG_EXTRACTOR,
|
||||
N_("BLOCK"), N_("Define a menu entry."), options);
|
||||
cmd_sub = grub_register_extcmd ("submenu", grub_cmd_menuentry,
|
||||
GRUB_COMMAND_FLAG_BLOCKS
|
||||
| GRUB_COMMAND_ACCEPT_DASH
|
||||
| GRUB_COMMAND_FLAG_EXTRACTOR,
|
||||
N_("BLOCK"), N_("Define a submenu."),
|
||||
options);
|
||||
}
|
||||
|
||||
void
|
||||
grub_menu_fini (void)
|
||||
{
|
||||
grub_unregister_extcmd (cmd);
|
||||
grub_unregister_extcmd (cmd_sub);
|
||||
}
|
839
GRUB2/MOD_SRC/grub-2.04/grub-core/gfxmenu/theme_loader.c
Normal file
@@ -0,0 +1,839 @@
|
||||
/* theme_loader.c - Theme file loader for gfxmenu. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/types.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/video.h>
|
||||
#include <grub/gui_string_util.h>
|
||||
#include <grub/bitmap.h>
|
||||
#include <grub/bitmap_scale.h>
|
||||
#include <grub/gfxwidgets.h>
|
||||
#include <grub/gfxmenu_view.h>
|
||||
#include <grub/gui.h>
|
||||
#include <grub/color.h>
|
||||
#include <grub/env.h>
|
||||
|
||||
static grub_err_t
|
||||
parse_proportional_spec (const char *value, signed *abs, grub_fixed_signed_t *prop);
|
||||
|
||||
/* Construct a new box widget using ABSPATTERN to find the pixmap files for
|
||||
it, storing the new box instance at *BOXPTR.
|
||||
PATTERN should be of the form: "(hd0,0)/somewhere/style*.png".
|
||||
The '*' then gets substituted with the various pixmap names that the
|
||||
box uses. */
|
||||
static grub_err_t
|
||||
recreate_box_absolute (grub_gfxmenu_box_t *boxptr, const char *abspattern)
|
||||
{
|
||||
char *prefix;
|
||||
char *suffix;
|
||||
char *star;
|
||||
grub_gfxmenu_box_t box;
|
||||
|
||||
star = grub_strchr (abspattern, '*');
|
||||
if (! star)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"missing `*' in box pixmap pattern `%s'", abspattern);
|
||||
|
||||
/* Prefix: Get the part before the '*'. */
|
||||
prefix = grub_malloc (star - abspattern + 1);
|
||||
if (! prefix)
|
||||
return grub_errno;
|
||||
|
||||
grub_memcpy (prefix, abspattern, star - abspattern);
|
||||
prefix[star - abspattern] = '\0';
|
||||
|
||||
/* Suffix: Everything after the '*' is the suffix. */
|
||||
suffix = star + 1;
|
||||
|
||||
box = grub_gfxmenu_create_box (prefix, suffix);
|
||||
grub_free (prefix);
|
||||
if (! box)
|
||||
return grub_errno;
|
||||
|
||||
if (*boxptr)
|
||||
(*boxptr)->destroy (*boxptr);
|
||||
*boxptr = box;
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
|
||||
/* Construct a new box widget using PATTERN to find the pixmap files for it,
|
||||
storing the new widget at *BOXPTR. PATTERN should be of the form:
|
||||
"somewhere/style*.png". The '*' then gets substituted with the various
|
||||
pixmap names that the widget uses.
|
||||
|
||||
Important! The value of *BOXPTR must be initialized! It must either
|
||||
(1) Be 0 (a NULL pointer), or
|
||||
(2) Be a pointer to a valid 'grub_gfxmenu_box_t' instance.
|
||||
In this case, the previous instance is destroyed. */
|
||||
grub_err_t
|
||||
grub_gui_recreate_box (grub_gfxmenu_box_t *boxptr,
|
||||
const char *pattern, const char *theme_dir)
|
||||
{
|
||||
char *abspattern;
|
||||
|
||||
/* Check arguments. */
|
||||
if (! pattern)
|
||||
{
|
||||
/* If no pixmap pattern is given, then just create an empty box. */
|
||||
if (*boxptr)
|
||||
(*boxptr)->destroy (*boxptr);
|
||||
*boxptr = grub_gfxmenu_create_box (0, 0);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
if (! theme_dir)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"styled box missing theme directory");
|
||||
|
||||
/* Resolve to an absolute path. */
|
||||
abspattern = grub_resolve_relative_path (theme_dir, pattern);
|
||||
if (! abspattern)
|
||||
return grub_errno;
|
||||
|
||||
/* Create the box. */
|
||||
recreate_box_absolute (boxptr, abspattern);
|
||||
grub_free (abspattern);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
theme_get_unsigned_int_from_proportional (const char *value,
|
||||
unsigned absolute_value,
|
||||
unsigned int *parsed_value)
|
||||
{
|
||||
grub_err_t err;
|
||||
grub_fixed_signed_t frac;
|
||||
signed pixels;
|
||||
err = parse_proportional_spec (value, &pixels, &frac);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
int result = grub_fixed_sfs_multiply (absolute_value, frac) + pixels;
|
||||
if (result < 0)
|
||||
result = 0;
|
||||
*parsed_value = result;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
/* Set the specified property NAME on the view to the given string VALUE.
|
||||
The caller is responsible for the lifetimes of NAME and VALUE. */
|
||||
static grub_err_t
|
||||
theme_set_string (grub_gfxmenu_view_t view,
|
||||
const char *name,
|
||||
const char *value,
|
||||
const char *theme_dir,
|
||||
const char *filename,
|
||||
int line_num,
|
||||
int col_num)
|
||||
{
|
||||
if (! grub_strcmp ("title-font", name))
|
||||
view->title_font = grub_font_get (value);
|
||||
else if (! grub_strcmp ("message-font", name))
|
||||
view->message_font = grub_font_get (value);
|
||||
else if (! grub_strcmp ("terminal-font", name))
|
||||
{
|
||||
grub_free (view->terminal_font_name);
|
||||
view->terminal_font_name = grub_strdup (value);
|
||||
if (! view->terminal_font_name)
|
||||
return grub_errno;
|
||||
}
|
||||
else if (! grub_strcmp ("title-color", name))
|
||||
grub_video_parse_color (value, &view->title_color);
|
||||
else if (! grub_strcmp ("message-color", name))
|
||||
grub_video_parse_color (value, &view->message_color);
|
||||
else if (! grub_strcmp ("message-bg-color", name))
|
||||
grub_video_parse_color (value, &view->message_bg_color);
|
||||
else if (! grub_strcmp ("desktop-image", name))
|
||||
{
|
||||
struct grub_video_bitmap *raw_bitmap;
|
||||
char *path;
|
||||
path = grub_resolve_relative_path (theme_dir, value);
|
||||
if (! path)
|
||||
return grub_errno;
|
||||
if (grub_video_bitmap_load (&raw_bitmap, path) != GRUB_ERR_NONE)
|
||||
{
|
||||
grub_free (path);
|
||||
return grub_errno;
|
||||
}
|
||||
grub_free(path);
|
||||
grub_video_bitmap_destroy (view->raw_desktop_image);
|
||||
view->raw_desktop_image = raw_bitmap;
|
||||
}
|
||||
else if (! grub_strcmp ("desktop-image-scale-method", name))
|
||||
{
|
||||
if (! value || ! grub_strcmp ("stretch", value))
|
||||
view->desktop_image_scale_method =
|
||||
GRUB_VIDEO_BITMAP_SELECTION_METHOD_STRETCH;
|
||||
else if (! grub_strcmp ("crop", value))
|
||||
view->desktop_image_scale_method =
|
||||
GRUB_VIDEO_BITMAP_SELECTION_METHOD_CROP;
|
||||
else if (! grub_strcmp ("padding", value))
|
||||
view->desktop_image_scale_method =
|
||||
GRUB_VIDEO_BITMAP_SELECTION_METHOD_PADDING;
|
||||
else if (! grub_strcmp ("fitwidth", value))
|
||||
view->desktop_image_scale_method =
|
||||
GRUB_VIDEO_BITMAP_SELECTION_METHOD_FITWIDTH;
|
||||
else if (! grub_strcmp ("fitheight", value))
|
||||
view->desktop_image_scale_method =
|
||||
GRUB_VIDEO_BITMAP_SELECTION_METHOD_FITHEIGHT;
|
||||
else
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"Unsupported scale method: %s",
|
||||
value);
|
||||
}
|
||||
else if (! grub_strcmp ("desktop-image-h-align", name))
|
||||
{
|
||||
if (! grub_strcmp ("left", value))
|
||||
view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_LEFT;
|
||||
else if (! grub_strcmp ("center", value))
|
||||
view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_CENTER;
|
||||
else if (! grub_strcmp ("right", value))
|
||||
view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_RIGHT;
|
||||
else
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"Unsupported horizontal align method: %s",
|
||||
value);
|
||||
}
|
||||
else if (! grub_strcmp ("desktop-image-v-align", name))
|
||||
{
|
||||
if (! grub_strcmp ("top", value))
|
||||
view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_TOP;
|
||||
else if (! grub_strcmp ("center", value))
|
||||
view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_CENTER;
|
||||
else if (! grub_strcmp ("bottom", value))
|
||||
view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_BOTTOM;
|
||||
else
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"Unsupported vertical align method: %s",
|
||||
value);
|
||||
}
|
||||
else if (! grub_strcmp ("desktop-color", name))
|
||||
grub_video_parse_color (value, &view->desktop_color);
|
||||
else if (! grub_strcmp ("terminal-box", name))
|
||||
{
|
||||
grub_err_t err;
|
||||
err = grub_gui_recreate_box (&view->terminal_box, value, theme_dir);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
}
|
||||
else if (! grub_strcmp ("terminal-border", name))
|
||||
{
|
||||
view->terminal_border = grub_strtoul (value, 0, 10);
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
}
|
||||
else if (! grub_strcmp ("terminal-left", name))
|
||||
{
|
||||
unsigned int tmp;
|
||||
int err = theme_get_unsigned_int_from_proportional (value,
|
||||
view->screen.width,
|
||||
&tmp);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
view->terminal_rect.x = tmp;
|
||||
}
|
||||
else if (! grub_strcmp ("terminal-top", name))
|
||||
{
|
||||
unsigned int tmp;
|
||||
int err = theme_get_unsigned_int_from_proportional (value,
|
||||
view->screen.height,
|
||||
&tmp);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
view->terminal_rect.y = tmp;
|
||||
}
|
||||
else if (! grub_strcmp ("terminal-width", name))
|
||||
{
|
||||
unsigned int tmp;
|
||||
int err = theme_get_unsigned_int_from_proportional (value,
|
||||
view->screen.width,
|
||||
&tmp);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
view->terminal_rect.width = tmp;
|
||||
}
|
||||
else if (! grub_strcmp ("terminal-height", name))
|
||||
{
|
||||
unsigned int tmp;
|
||||
int err = theme_get_unsigned_int_from_proportional (value,
|
||||
view->screen.height,
|
||||
&tmp);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
view->terminal_rect.height = tmp;
|
||||
}
|
||||
else if (! grub_strcmp ("title-text", name))
|
||||
{
|
||||
grub_free (view->title_text);
|
||||
view->title_text = grub_strdup (value);
|
||||
if (! view->title_text)
|
||||
return grub_errno;
|
||||
}
|
||||
else
|
||||
{
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"%s:%d:%d unknown property `%s'",
|
||||
filename, line_num, col_num, name);
|
||||
}
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
struct parsebuf
|
||||
{
|
||||
char *buf;
|
||||
int pos;
|
||||
int len;
|
||||
int line_num;
|
||||
int col_num;
|
||||
const char *filename;
|
||||
char *theme_dir;
|
||||
grub_gfxmenu_view_t view;
|
||||
};
|
||||
|
||||
static int
|
||||
has_more (struct parsebuf *p)
|
||||
{
|
||||
return p->pos < p->len;
|
||||
}
|
||||
|
||||
static int
|
||||
read_char (struct parsebuf *p)
|
||||
{
|
||||
if (has_more (p))
|
||||
{
|
||||
char c;
|
||||
c = p->buf[p->pos++];
|
||||
if (c == '\n')
|
||||
{
|
||||
p->line_num++;
|
||||
p->col_num = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
p->col_num++;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
peek_char (struct parsebuf *p)
|
||||
{
|
||||
if (has_more (p))
|
||||
return p->buf[p->pos];
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
is_whitespace (char c)
|
||||
{
|
||||
return (c == ' '
|
||||
|| c == '\t'
|
||||
|| c == '\r'
|
||||
|| c == '\n'
|
||||
|| c == '\f');
|
||||
}
|
||||
|
||||
static void
|
||||
skip_whitespace (struct parsebuf *p)
|
||||
{
|
||||
while (has_more (p) && is_whitespace(peek_char (p)))
|
||||
read_char (p);
|
||||
}
|
||||
|
||||
static void
|
||||
advance_to_next_line (struct parsebuf *p)
|
||||
{
|
||||
int c;
|
||||
|
||||
/* Eat characters up to the newline. */
|
||||
do
|
||||
{
|
||||
c = read_char (p);
|
||||
}
|
||||
while (c != -1 && c != '\n');
|
||||
}
|
||||
|
||||
static int
|
||||
is_identifier_char (int c)
|
||||
{
|
||||
return (c != -1
|
||||
&& (grub_isalpha(c)
|
||||
|| grub_isdigit(c)
|
||||
|| c == '_'
|
||||
|| c == '-'));
|
||||
}
|
||||
|
||||
static char *
|
||||
read_identifier (struct parsebuf *p)
|
||||
{
|
||||
/* Index of the first character of the identifier in p->buf. */
|
||||
int start;
|
||||
/* Next index after the last character of the identifer in p->buf. */
|
||||
int end;
|
||||
|
||||
skip_whitespace (p);
|
||||
|
||||
/* Capture the start of the identifier. */
|
||||
start = p->pos;
|
||||
|
||||
/* Scan for the end. */
|
||||
while (is_identifier_char (peek_char (p)))
|
||||
read_char (p);
|
||||
end = p->pos;
|
||||
|
||||
if (end - start < 1)
|
||||
return 0;
|
||||
|
||||
return grub_new_substring (p->buf, start, end);
|
||||
}
|
||||
|
||||
static char *
|
||||
read_expression (struct parsebuf *p)
|
||||
{
|
||||
int start;
|
||||
int end;
|
||||
|
||||
skip_whitespace (p);
|
||||
if (peek_char (p) == '"')
|
||||
{
|
||||
/* Read as a quoted string.
|
||||
The quotation marks are not included in the expression value. */
|
||||
/* Skip opening quotation mark. */
|
||||
read_char (p);
|
||||
start = p->pos;
|
||||
while (has_more (p) && peek_char (p) != '"')
|
||||
read_char (p);
|
||||
end = p->pos;
|
||||
/* Skip the terminating quotation mark. */
|
||||
read_char (p);
|
||||
}
|
||||
else if (peek_char (p) == '(')
|
||||
{
|
||||
/* Read as a parenthesized string -- for tuples/coordinates. */
|
||||
/* The parentheses are included in the expression value. */
|
||||
int c;
|
||||
|
||||
start = p->pos;
|
||||
do
|
||||
{
|
||||
c = read_char (p);
|
||||
}
|
||||
while (c != -1 && c != ')');
|
||||
end = p->pos;
|
||||
}
|
||||
else if (has_more (p))
|
||||
{
|
||||
/* Read as a single word -- for numeric values or words without
|
||||
whitespace. */
|
||||
start = p->pos;
|
||||
while (has_more (p) && ! is_whitespace (peek_char (p)))
|
||||
read_char (p);
|
||||
end = p->pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The end of the theme file has been reached. */
|
||||
grub_error (GRUB_ERR_IO, "%s:%d:%d expression expected in theme file",
|
||||
p->filename, p->line_num, p->col_num);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return grub_new_substring (p->buf, start, end);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
parse_proportional_spec (const char *value, signed *abs, grub_fixed_signed_t *prop)
|
||||
{
|
||||
signed num;
|
||||
const char *ptr;
|
||||
int sig = 0;
|
||||
*abs = 0;
|
||||
*prop = 0;
|
||||
ptr = value;
|
||||
while (*ptr)
|
||||
{
|
||||
sig = 0;
|
||||
|
||||
while (*ptr == '-' || *ptr == '+')
|
||||
{
|
||||
if (*ptr == '-')
|
||||
sig = !sig;
|
||||
ptr++;
|
||||
}
|
||||
|
||||
num = grub_strtoul (ptr, (char **) &ptr, 0);
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
if (sig)
|
||||
num = -num;
|
||||
if (*ptr == '%')
|
||||
{
|
||||
*prop += grub_fixed_fsf_divide (grub_signed_to_fixed (num), 100);
|
||||
ptr++;
|
||||
}
|
||||
else
|
||||
*abs += num;
|
||||
}
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
|
||||
/* Read a GUI object specification from the theme file.
|
||||
Any components created will be added to the GUI container PARENT. */
|
||||
static grub_err_t
|
||||
read_object (struct parsebuf *p, grub_gui_container_t parent)
|
||||
{
|
||||
grub_video_rect_t bounds;
|
||||
|
||||
char *name;
|
||||
name = read_identifier (p);
|
||||
if (! name)
|
||||
goto cleanup;
|
||||
|
||||
grub_gui_component_t component = 0;
|
||||
if (grub_strcmp (name, "label") == 0)
|
||||
{
|
||||
component = grub_gui_label_new ();
|
||||
}
|
||||
else if (grub_strcmp (name, "image") == 0)
|
||||
{
|
||||
component = grub_gui_image_new ();
|
||||
}
|
||||
else if (grub_strcmp (name, "vbox") == 0)
|
||||
{
|
||||
component = (grub_gui_component_t) grub_gui_vbox_new ();
|
||||
}
|
||||
else if (grub_strcmp (name, "hbox") == 0)
|
||||
{
|
||||
component = (grub_gui_component_t) grub_gui_hbox_new ();
|
||||
}
|
||||
else if (grub_strcmp (name, "canvas") == 0)
|
||||
{
|
||||
component = (grub_gui_component_t) grub_gui_canvas_new ();
|
||||
}
|
||||
else if (grub_strcmp (name, "progress_bar") == 0)
|
||||
{
|
||||
component = grub_gui_progress_bar_new ();
|
||||
}
|
||||
else if (grub_strcmp (name, "circular_progress") == 0)
|
||||
{
|
||||
component = grub_gui_circular_progress_new ();
|
||||
}
|
||||
else if (grub_strcmp (name, "boot_menu") == 0)
|
||||
{
|
||||
component = grub_gui_list_new ();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unknown type. */
|
||||
grub_error (GRUB_ERR_IO, "%s:%d:%d unknown object type `%s'",
|
||||
p->filename, p->line_num, p->col_num, name);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (! component)
|
||||
goto cleanup;
|
||||
|
||||
/* Inform the component about the theme so it can find its resources. */
|
||||
component->ops->set_property (component, "theme_dir", p->theme_dir);
|
||||
component->ops->set_property (component, "theme_path", p->filename);
|
||||
|
||||
/* Add the component as a child of PARENT. */
|
||||
bounds.x = 0;
|
||||
bounds.y = 0;
|
||||
bounds.width = -1;
|
||||
bounds.height = -1;
|
||||
component->ops->set_bounds (component, &bounds);
|
||||
parent->ops->add (parent, component);
|
||||
|
||||
skip_whitespace (p);
|
||||
if (read_char (p) != '{')
|
||||
{
|
||||
grub_error (GRUB_ERR_IO,
|
||||
"%s:%d:%d expected `{' after object type name `%s'",
|
||||
p->filename, p->line_num, p->col_num, name);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
while (has_more (p))
|
||||
{
|
||||
skip_whitespace (p);
|
||||
|
||||
/* Check whether the end has been encountered. */
|
||||
if (peek_char (p) == '}')
|
||||
{
|
||||
/* Skip the closing brace. */
|
||||
read_char (p);
|
||||
break;
|
||||
}
|
||||
|
||||
if (peek_char (p) == '#')
|
||||
{
|
||||
/* Skip comments. */
|
||||
advance_to_next_line (p);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (peek_char (p) == '+')
|
||||
{
|
||||
/* Skip the '+'. */
|
||||
read_char (p);
|
||||
|
||||
/* Check whether this component is a container. */
|
||||
if (component->ops->is_instance (component, "container"))
|
||||
{
|
||||
/* Read the sub-object recursively and add it as a child. */
|
||||
if (read_object (p, (grub_gui_container_t) component) != 0)
|
||||
goto cleanup;
|
||||
/* After reading the sub-object, resume parsing, expecting
|
||||
another property assignment or sub-object definition. */
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_error (GRUB_ERR_IO,
|
||||
"%s:%d:%d attempted to add object to non-container",
|
||||
p->filename, p->line_num, p->col_num);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
char *property;
|
||||
property = read_identifier (p);
|
||||
if (! property)
|
||||
{
|
||||
grub_error (GRUB_ERR_IO, "%s:%d:%d identifier expected in theme file",
|
||||
p->filename, p->line_num, p->col_num);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
skip_whitespace (p);
|
||||
if (read_char (p) != '=')
|
||||
{
|
||||
grub_error (GRUB_ERR_IO,
|
||||
"%s:%d:%d expected `=' after property name `%s'",
|
||||
p->filename, p->line_num, p->col_num, property);
|
||||
grub_free (property);
|
||||
goto cleanup;
|
||||
}
|
||||
skip_whitespace (p);
|
||||
|
||||
char *value;
|
||||
value = read_expression (p);
|
||||
if (! value)
|
||||
{
|
||||
grub_free (property);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Handle the property value. */
|
||||
if (grub_strcmp (property, "left") == 0)
|
||||
parse_proportional_spec (value, &component->x, &component->xfrac);
|
||||
else if (grub_strcmp (property, "top") == 0)
|
||||
parse_proportional_spec (value, &component->y, &component->yfrac);
|
||||
else if (grub_strcmp (property, "width") == 0)
|
||||
parse_proportional_spec (value, &component->w, &component->wfrac);
|
||||
else if (grub_strcmp (property, "height") == 0)
|
||||
parse_proportional_spec (value, &component->h, &component->hfrac);
|
||||
else
|
||||
/* General property handling. */
|
||||
component->ops->set_property (component, property, value);
|
||||
|
||||
grub_free (value);
|
||||
grub_free (property);
|
||||
if (grub_errno != GRUB_ERR_NONE)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
grub_free (name);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
read_property (struct parsebuf *p)
|
||||
{
|
||||
char *name;
|
||||
|
||||
/* Read the property name. */
|
||||
name = read_identifier (p);
|
||||
if (! name)
|
||||
{
|
||||
advance_to_next_line (p);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
/* Skip whitespace before separator. */
|
||||
skip_whitespace (p);
|
||||
|
||||
/* Read separator. */
|
||||
if (read_char (p) != ':')
|
||||
{
|
||||
grub_error (GRUB_ERR_IO,
|
||||
"%s:%d:%d missing separator after property name `%s'",
|
||||
p->filename, p->line_num, p->col_num, name);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Skip whitespace after separator. */
|
||||
skip_whitespace (p);
|
||||
|
||||
/* Get the value based on its type. */
|
||||
if (peek_char (p) == '"')
|
||||
{
|
||||
/* String value (e.g., '"My string"'). */
|
||||
char *value = read_expression (p);
|
||||
if (! value)
|
||||
{
|
||||
grub_error (GRUB_ERR_IO, "%s:%d:%d missing property value",
|
||||
p->filename, p->line_num, p->col_num);
|
||||
goto done;
|
||||
}
|
||||
/* If theme_set_string results in an error, grub_errno will be returned
|
||||
below. */
|
||||
theme_set_string (p->view, name, value, p->theme_dir,
|
||||
p->filename, p->line_num, p->col_num);
|
||||
grub_free (value);
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_error (GRUB_ERR_IO,
|
||||
"%s:%d:%d property value invalid; "
|
||||
"enclose literal values in quotes (\")",
|
||||
p->filename, p->line_num, p->col_num);
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
grub_free (name);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
/* Set properties on the view based on settings from the specified
|
||||
theme file. */
|
||||
grub_err_t
|
||||
grub_gfxmenu_view_load_theme (grub_gfxmenu_view_t view, const char *theme_path)
|
||||
{
|
||||
grub_file_t file;
|
||||
struct parsebuf p;
|
||||
|
||||
p.view = view;
|
||||
p.theme_dir = grub_get_dirname (theme_path);
|
||||
|
||||
file = grub_file_open (theme_path, GRUB_FILE_TYPE_THEME);
|
||||
if (! file)
|
||||
{
|
||||
grub_free (p.theme_dir);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
p.len = grub_file_size (file);
|
||||
p.buf = grub_malloc (p.len + 4096);
|
||||
p.pos = 0;
|
||||
p.line_num = 1;
|
||||
p.col_num = 1;
|
||||
p.filename = theme_path;
|
||||
if (! p.buf)
|
||||
{
|
||||
grub_file_close (file);
|
||||
grub_free (p.theme_dir);
|
||||
return grub_errno;
|
||||
}
|
||||
if (grub_file_read (file, p.buf, p.len) != p.len)
|
||||
{
|
||||
grub_free (p.buf);
|
||||
grub_file_close (file);
|
||||
grub_free (p.theme_dir);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
{
|
||||
const char *checkret = grub_env_get("VTOY_CHKDEV_RESULT_STRING");
|
||||
if (checkret == NULL || checkret[0] != '0')
|
||||
{
|
||||
p.len += grub_snprintf(p.buf + p.len, 4096, "\n+ hbox{\n left = 1%%\n top = 90%%\n"
|
||||
" + label {text = \"[Unofficial Ventoy]\" color = \"red\" align = \"left\"}\n"
|
||||
"}\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (view->canvas)
|
||||
view->canvas->component.ops->destroy (view->canvas);
|
||||
|
||||
view->canvas = grub_gui_canvas_new ();
|
||||
if (!view->canvas)
|
||||
goto fail;
|
||||
((grub_gui_component_t) view->canvas)
|
||||
->ops->set_bounds ((grub_gui_component_t) view->canvas,
|
||||
&view->screen);
|
||||
|
||||
while (has_more (&p))
|
||||
{
|
||||
/* Skip comments (lines beginning with #). */
|
||||
if (peek_char (&p) == '#')
|
||||
{
|
||||
advance_to_next_line (&p);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Find the first non-whitespace character. */
|
||||
skip_whitespace (&p);
|
||||
|
||||
/* Handle the content. */
|
||||
if (peek_char (&p) == '+')
|
||||
{
|
||||
/* Skip the '+'. */
|
||||
read_char (&p);
|
||||
read_object (&p, view->canvas);
|
||||
}
|
||||
else
|
||||
{
|
||||
read_property (&p);
|
||||
}
|
||||
|
||||
if (grub_errno != GRUB_ERR_NONE)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Set the new theme path. */
|
||||
grub_free (view->theme_path);
|
||||
view->theme_path = grub_strdup (theme_path);
|
||||
goto cleanup;
|
||||
|
||||
fail:
|
||||
if (view->canvas)
|
||||
{
|
||||
view->canvas->component.ops->destroy (view->canvas);
|
||||
view->canvas = 0;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
grub_free (p.buf);
|
||||
grub_file_close (file);
|
||||
grub_free (p.theme_dir);
|
||||
return grub_errno;
|
||||
}
|
647
GRUB2/MOD_SRC/grub-2.04/grub-core/gfxmenu/view.c
Normal file
@@ -0,0 +1,647 @@
|
||||
/* view.c - Graphical menu interface MVC view. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/types.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/video.h>
|
||||
#include <grub/gfxterm.h>
|
||||
#include <grub/bitmap.h>
|
||||
#include <grub/bitmap_scale.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/gfxwidgets.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/menu.h>
|
||||
#include <grub/menu_viewer.h>
|
||||
#include <grub/gfxmenu_view.h>
|
||||
#include <grub/gui_string_util.h>
|
||||
#include <grub/icon_manager.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static void
|
||||
init_terminal (grub_gfxmenu_view_t view);
|
||||
static void
|
||||
init_background (grub_gfxmenu_view_t view);
|
||||
static grub_gfxmenu_view_t term_view;
|
||||
|
||||
/* Create a new view object, loading the theme specified by THEME_PATH and
|
||||
associating MODEL with the view. */
|
||||
grub_gfxmenu_view_t
|
||||
grub_gfxmenu_view_new (const char *theme_path,
|
||||
int width, int height)
|
||||
{
|
||||
grub_gfxmenu_view_t view;
|
||||
grub_font_t default_font;
|
||||
grub_video_rgba_color_t default_fg_color;
|
||||
grub_video_rgba_color_t default_bg_color;
|
||||
|
||||
view = grub_malloc (sizeof (*view));
|
||||
if (! view)
|
||||
return 0;
|
||||
|
||||
while (grub_gfxmenu_timeout_notifications)
|
||||
{
|
||||
struct grub_gfxmenu_timeout_notify *p;
|
||||
p = grub_gfxmenu_timeout_notifications;
|
||||
grub_gfxmenu_timeout_notifications = grub_gfxmenu_timeout_notifications->next;
|
||||
grub_free (p);
|
||||
}
|
||||
|
||||
view->screen.x = 0;
|
||||
view->screen.y = 0;
|
||||
view->screen.width = width;
|
||||
view->screen.height = height;
|
||||
|
||||
view->need_to_check_sanity = 1;
|
||||
view->terminal_border = 3;
|
||||
view->terminal_rect.width = view->screen.width * 7 / 10;
|
||||
view->terminal_rect.height = view->screen.height * 7 / 10;
|
||||
view->terminal_rect.x = view->screen.x + (view->screen.width
|
||||
- view->terminal_rect.width) / 2;
|
||||
view->terminal_rect.y = view->screen.y + (view->screen.height
|
||||
- view->terminal_rect.height) / 2;
|
||||
|
||||
default_font = grub_font_get ("Unknown Regular 16");
|
||||
default_fg_color = grub_video_rgba_color_rgb (0, 0, 0);
|
||||
default_bg_color = grub_video_rgba_color_rgb (255, 255, 255);
|
||||
|
||||
view->canvas = 0;
|
||||
|
||||
view->title_font = default_font;
|
||||
view->message_font = default_font;
|
||||
view->terminal_font_name = grub_strdup ("Fixed 10");
|
||||
view->title_color = default_fg_color;
|
||||
view->message_color = default_bg_color;
|
||||
view->message_bg_color = default_fg_color;
|
||||
view->raw_desktop_image = 0;
|
||||
view->scaled_desktop_image = 0;
|
||||
view->desktop_image_scale_method = GRUB_VIDEO_BITMAP_SELECTION_METHOD_STRETCH;
|
||||
view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_CENTER;
|
||||
view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_CENTER;
|
||||
view->desktop_color = default_bg_color;
|
||||
view->terminal_box = grub_gfxmenu_create_box (0, 0);
|
||||
view->title_text = grub_strdup (_("GRUB Boot Menu"));
|
||||
view->progress_message_text = 0;
|
||||
view->theme_path = 0;
|
||||
|
||||
/* Set the timeout bar's frame. */
|
||||
view->progress_message_frame.width = view->screen.width * 4 / 5;
|
||||
view->progress_message_frame.height = 50;
|
||||
view->progress_message_frame.x = view->screen.x
|
||||
+ (view->screen.width - view->progress_message_frame.width) / 2;
|
||||
view->progress_message_frame.y = view->screen.y
|
||||
+ view->screen.height - 90 - 20 - view->progress_message_frame.height;
|
||||
|
||||
if (grub_gfxmenu_view_load_theme (view, theme_path) != 0)
|
||||
{
|
||||
grub_gfxmenu_view_destroy (view);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
/* Destroy the view object. All used memory is freed. */
|
||||
void
|
||||
grub_gfxmenu_view_destroy (grub_gfxmenu_view_t view)
|
||||
{
|
||||
if (!view)
|
||||
return;
|
||||
while (grub_gfxmenu_timeout_notifications)
|
||||
{
|
||||
struct grub_gfxmenu_timeout_notify *p;
|
||||
p = grub_gfxmenu_timeout_notifications;
|
||||
grub_gfxmenu_timeout_notifications = grub_gfxmenu_timeout_notifications->next;
|
||||
grub_free (p);
|
||||
}
|
||||
grub_video_bitmap_destroy (view->raw_desktop_image);
|
||||
grub_video_bitmap_destroy (view->scaled_desktop_image);
|
||||
if (view->terminal_box)
|
||||
view->terminal_box->destroy (view->terminal_box);
|
||||
grub_free (view->terminal_font_name);
|
||||
grub_free (view->title_text);
|
||||
grub_free (view->progress_message_text);
|
||||
grub_free (view->theme_path);
|
||||
if (view->canvas)
|
||||
view->canvas->component.ops->destroy (view->canvas);
|
||||
grub_free (view);
|
||||
}
|
||||
|
||||
static void
|
||||
redraw_background (grub_gfxmenu_view_t view,
|
||||
const grub_video_rect_t *bounds)
|
||||
{
|
||||
if (view->scaled_desktop_image)
|
||||
{
|
||||
struct grub_video_bitmap *img = view->scaled_desktop_image;
|
||||
grub_video_blit_bitmap (img, GRUB_VIDEO_BLIT_REPLACE,
|
||||
bounds->x, bounds->y,
|
||||
bounds->x - view->screen.x,
|
||||
bounds->y - view->screen.y,
|
||||
bounds->width, bounds->height);
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_video_fill_rect (grub_video_map_rgba_color (view->desktop_color),
|
||||
bounds->x, bounds->y,
|
||||
bounds->width, bounds->height);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
draw_title (grub_gfxmenu_view_t view)
|
||||
{
|
||||
if (! view->title_text)
|
||||
return;
|
||||
|
||||
/* Center the title. */
|
||||
int title_width = grub_font_get_string_width (view->title_font,
|
||||
view->title_text);
|
||||
int x = (view->screen.width - title_width) / 2;
|
||||
int y = 40 + grub_font_get_ascent (view->title_font);
|
||||
grub_font_draw_string (view->title_text,
|
||||
view->title_font,
|
||||
grub_video_map_rgba_color (view->title_color),
|
||||
x, y);
|
||||
}
|
||||
|
||||
struct progress_value_data
|
||||
{
|
||||
int visible;
|
||||
int start;
|
||||
int end;
|
||||
int value;
|
||||
};
|
||||
|
||||
struct grub_gfxmenu_timeout_notify *grub_gfxmenu_timeout_notifications;
|
||||
|
||||
static void
|
||||
update_timeouts (int visible, int start, int value, int end)
|
||||
{
|
||||
struct grub_gfxmenu_timeout_notify *cur;
|
||||
|
||||
for (cur = grub_gfxmenu_timeout_notifications; cur; cur = cur->next)
|
||||
cur->set_state (cur->self, visible, start, value, end);
|
||||
}
|
||||
|
||||
static void
|
||||
redraw_timeouts (struct grub_gfxmenu_view *view)
|
||||
{
|
||||
struct grub_gfxmenu_timeout_notify *cur;
|
||||
|
||||
for (cur = grub_gfxmenu_timeout_notifications; cur; cur = cur->next)
|
||||
{
|
||||
grub_video_rect_t bounds;
|
||||
cur->self->ops->get_bounds (cur->self, &bounds);
|
||||
grub_video_set_area_status (GRUB_VIDEO_AREA_ENABLED);
|
||||
grub_gfxmenu_view_redraw (view, &bounds);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
grub_gfxmenu_print_timeout (int timeout, void *data)
|
||||
{
|
||||
struct grub_gfxmenu_view *view = data;
|
||||
|
||||
if (view->first_timeout == -1)
|
||||
view->first_timeout = timeout;
|
||||
|
||||
update_timeouts (1, -view->first_timeout, -timeout, 0);
|
||||
redraw_timeouts (view);
|
||||
grub_video_swap_buffers ();
|
||||
if (view->double_repaint)
|
||||
redraw_timeouts (view);
|
||||
}
|
||||
|
||||
void
|
||||
grub_gfxmenu_clear_timeout (void *data)
|
||||
{
|
||||
struct grub_gfxmenu_view *view = data;
|
||||
|
||||
update_timeouts (0, 1, 0, 0);
|
||||
redraw_timeouts (view);
|
||||
grub_video_swap_buffers ();
|
||||
if (view->double_repaint)
|
||||
redraw_timeouts (view);
|
||||
}
|
||||
|
||||
static void
|
||||
update_menu_visit (grub_gui_component_t component,
|
||||
void *userdata)
|
||||
{
|
||||
grub_gfxmenu_view_t view;
|
||||
view = userdata;
|
||||
if (component->ops->is_instance (component, "list"))
|
||||
{
|
||||
grub_gui_list_t list = (grub_gui_list_t) component;
|
||||
list->ops->set_view_info (list, view);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update any boot menu components with the current menu model and
|
||||
theme path. */
|
||||
static void
|
||||
update_menu_components (grub_gfxmenu_view_t view)
|
||||
{
|
||||
grub_gui_iterate_recursively ((grub_gui_component_t) view->canvas,
|
||||
update_menu_visit, view);
|
||||
}
|
||||
|
||||
static void
|
||||
refresh_menu_visit (grub_gui_component_t component,
|
||||
void *userdata)
|
||||
{
|
||||
grub_gfxmenu_view_t view;
|
||||
view = userdata;
|
||||
if (component->ops->is_instance (component, "list"))
|
||||
{
|
||||
grub_gui_list_t list = (grub_gui_list_t) component;
|
||||
list->ops->refresh_list (list, view);
|
||||
}
|
||||
}
|
||||
|
||||
/* Refresh list information (useful for submenus) */
|
||||
static void
|
||||
refresh_menu_components (grub_gfxmenu_view_t view)
|
||||
{
|
||||
grub_gui_iterate_recursively ((grub_gui_component_t) view->canvas,
|
||||
refresh_menu_visit, view);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_message (grub_gfxmenu_view_t view)
|
||||
{
|
||||
char *text = view->progress_message_text;
|
||||
grub_video_rect_t f = view->progress_message_frame;
|
||||
if (! text)
|
||||
return;
|
||||
|
||||
grub_font_t font = view->message_font;
|
||||
grub_video_color_t color = grub_video_map_rgba_color (view->message_color);
|
||||
|
||||
/* Border. */
|
||||
grub_video_fill_rect (color,
|
||||
f.x-1, f.y-1, f.width+2, f.height+2);
|
||||
/* Fill. */
|
||||
grub_video_fill_rect (grub_video_map_rgba_color (view->message_bg_color),
|
||||
f.x, f.y, f.width, f.height);
|
||||
|
||||
/* Center the text. */
|
||||
int text_width = grub_font_get_string_width (font, text);
|
||||
int x = f.x + (f.width - text_width) / 2;
|
||||
int y = (f.y + (f.height - grub_font_get_descent (font)) / 2
|
||||
+ grub_font_get_ascent (font) / 2);
|
||||
grub_font_draw_string (text, font, color, x, y);
|
||||
}
|
||||
|
||||
void
|
||||
grub_gfxmenu_view_redraw (grub_gfxmenu_view_t view,
|
||||
const grub_video_rect_t *region)
|
||||
{
|
||||
if (grub_video_have_common_points (&view->terminal_rect, region))
|
||||
grub_gfxterm_schedule_repaint ();
|
||||
|
||||
grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
|
||||
grub_video_area_status_t area_status;
|
||||
grub_video_get_area_status (&area_status);
|
||||
if (area_status == GRUB_VIDEO_AREA_ENABLED)
|
||||
grub_video_set_region (region->x, region->y,
|
||||
region->width, region->height);
|
||||
|
||||
redraw_background (view, region);
|
||||
if (view->canvas)
|
||||
view->canvas->component.ops->paint (view->canvas, region);
|
||||
draw_title (view);
|
||||
if (grub_video_have_common_points (&view->progress_message_frame, region))
|
||||
draw_message (view);
|
||||
|
||||
if (area_status == GRUB_VIDEO_AREA_ENABLED)
|
||||
grub_video_set_area_status (GRUB_VIDEO_AREA_ENABLED);
|
||||
}
|
||||
|
||||
void
|
||||
grub_gfxmenu_view_draw (grub_gfxmenu_view_t view)
|
||||
{
|
||||
init_terminal (view);
|
||||
|
||||
init_background (view);
|
||||
|
||||
/* Clear the screen; there may be garbage left over in video memory. */
|
||||
grub_video_fill_rect (grub_video_map_rgb (0, 0, 0),
|
||||
view->screen.x, view->screen.y,
|
||||
view->screen.width, view->screen.height);
|
||||
grub_video_swap_buffers ();
|
||||
if (view->double_repaint)
|
||||
grub_video_fill_rect (grub_video_map_rgb (0, 0, 0),
|
||||
view->screen.x, view->screen.y,
|
||||
view->screen.width, view->screen.height);
|
||||
|
||||
refresh_menu_components (view);
|
||||
update_menu_components (view);
|
||||
|
||||
grub_video_set_area_status (GRUB_VIDEO_AREA_DISABLED);
|
||||
grub_gfxmenu_view_redraw (view, &view->screen);
|
||||
grub_video_swap_buffers ();
|
||||
if (view->double_repaint)
|
||||
{
|
||||
grub_video_set_area_status (GRUB_VIDEO_AREA_DISABLED);
|
||||
grub_gfxmenu_view_redraw (view, &view->screen);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
redraw_menu_visit (grub_gui_component_t component,
|
||||
void *userdata)
|
||||
{
|
||||
grub_gfxmenu_view_t view;
|
||||
view = userdata;
|
||||
if (component->ops->is_instance (component, "list"))
|
||||
{
|
||||
grub_video_rect_t bounds;
|
||||
|
||||
component->ops->get_bounds (component, &bounds);
|
||||
grub_video_set_area_status (GRUB_VIDEO_AREA_ENABLED);
|
||||
grub_gfxmenu_view_redraw (view, &bounds);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
grub_gfxmenu_redraw_menu (grub_gfxmenu_view_t view)
|
||||
{
|
||||
update_menu_components (view);
|
||||
|
||||
grub_gui_iterate_recursively ((grub_gui_component_t) view->canvas,
|
||||
redraw_menu_visit, view);
|
||||
grub_video_swap_buffers ();
|
||||
if (view->double_repaint)
|
||||
{
|
||||
grub_gui_iterate_recursively ((grub_gui_component_t) view->canvas,
|
||||
redraw_menu_visit, view);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
grub_gfxmenu_set_chosen_entry (int entry, void *data)
|
||||
{
|
||||
grub_gfxmenu_view_t view = data;
|
||||
|
||||
view->selected = entry;
|
||||
grub_gfxmenu_redraw_menu (view);
|
||||
}
|
||||
|
||||
static void
|
||||
grub_gfxmenu_draw_terminal_box (void)
|
||||
{
|
||||
grub_gfxmenu_box_t term_box;
|
||||
|
||||
term_box = term_view->terminal_box;
|
||||
if (!term_box)
|
||||
return;
|
||||
|
||||
grub_video_set_area_status (GRUB_VIDEO_AREA_DISABLED);
|
||||
|
||||
term_box->set_content_size (term_box, term_view->terminal_rect.width,
|
||||
term_view->terminal_rect.height);
|
||||
|
||||
term_box->draw (term_box,
|
||||
term_view->terminal_rect.x - term_box->get_left_pad (term_box),
|
||||
term_view->terminal_rect.y - term_box->get_top_pad (term_box));
|
||||
}
|
||||
|
||||
static void
|
||||
get_min_terminal (grub_font_t terminal_font,
|
||||
unsigned int border_width,
|
||||
unsigned int *min_terminal_width,
|
||||
unsigned int *min_terminal_height)
|
||||
{
|
||||
struct grub_font_glyph *glyph;
|
||||
glyph = grub_font_get_glyph (terminal_font, 'M');
|
||||
*min_terminal_width = (glyph? glyph->device_width : 8) * 80
|
||||
+ 2 * border_width;
|
||||
*min_terminal_height = grub_font_get_max_char_height (terminal_font) * 24
|
||||
+ 2 * border_width;
|
||||
}
|
||||
|
||||
static void
|
||||
terminal_sanity_check (grub_gfxmenu_view_t view)
|
||||
{
|
||||
if (!view->need_to_check_sanity)
|
||||
return;
|
||||
|
||||
/* terminal_font was checked before in the init_terminal function. */
|
||||
grub_font_t terminal_font = grub_font_get (view->terminal_font_name);
|
||||
|
||||
/* Non-negative numbers below. */
|
||||
int scr_x = view->screen.x;
|
||||
int scr_y = view->screen.y;
|
||||
int scr_width = view->screen.width;
|
||||
int scr_height = view->screen.height;
|
||||
int term_x = view->terminal_rect.x;
|
||||
int term_y = view->terminal_rect.y;
|
||||
int term_width = view->terminal_rect.width;
|
||||
int term_height = view->terminal_rect.height;
|
||||
|
||||
/* Check that border_width isn't too big. */
|
||||
unsigned int border_width = view->terminal_border;
|
||||
unsigned int min_terminal_width;
|
||||
unsigned int min_terminal_height;
|
||||
get_min_terminal (terminal_font, border_width,
|
||||
&min_terminal_width, &min_terminal_height);
|
||||
if (border_width > 3 && ((int) min_terminal_width >= scr_width
|
||||
|| (int) min_terminal_height >= scr_height))
|
||||
{
|
||||
border_width = 3;
|
||||
get_min_terminal (terminal_font, border_width,
|
||||
&min_terminal_width, &min_terminal_height);
|
||||
}
|
||||
|
||||
/* Sanity checks. */
|
||||
if (term_width > scr_width)
|
||||
term_width = scr_width;
|
||||
if (term_height > scr_height)
|
||||
term_height = scr_height;
|
||||
|
||||
if (scr_width <= (int) min_terminal_width
|
||||
|| scr_height <= (int) min_terminal_height)
|
||||
{
|
||||
/* The screen resulution is too low. Use all space, except a small border
|
||||
to show the user, that it is a window. Then center the window. */
|
||||
term_width = scr_width - 6 * border_width;
|
||||
term_height = scr_height - 6 * border_width;
|
||||
term_x = scr_x + (scr_width - term_width) / 2;
|
||||
term_y = scr_y + (scr_height - term_height) / 2;
|
||||
}
|
||||
else if (term_width < (int) min_terminal_width
|
||||
|| term_height < (int) min_terminal_height)
|
||||
{
|
||||
/* The screen resolution is big enough. Make sure, that terminal screen
|
||||
dimensions aren't less than minimal values. Then center the window. */
|
||||
term_width = (int) min_terminal_width;
|
||||
term_height = (int) min_terminal_height;
|
||||
term_x = scr_x + (scr_width - term_width) / 2;
|
||||
term_y = scr_y + (scr_height - term_height) / 2;
|
||||
}
|
||||
|
||||
/* At this point w and h are satisfying. */
|
||||
if (term_x + term_width > scr_width)
|
||||
term_x = scr_width - term_width;
|
||||
if (term_y + term_height > scr_height)
|
||||
term_y = scr_height - term_height;
|
||||
|
||||
/* Write down corrected data. */
|
||||
view->terminal_rect.x = (unsigned int) term_x;
|
||||
view->terminal_rect.y = (unsigned int) term_y;
|
||||
view->terminal_rect.width = (unsigned int) term_width;
|
||||
view->terminal_rect.height = (unsigned int) term_height;
|
||||
view->terminal_border = border_width;
|
||||
|
||||
view->need_to_check_sanity = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
init_terminal (grub_gfxmenu_view_t view)
|
||||
{
|
||||
grub_font_t terminal_font;
|
||||
|
||||
terminal_font = grub_font_get (view->terminal_font_name);
|
||||
if (!terminal_font)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_FONT, "no font loaded");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check that terminal window size and position are sane. */
|
||||
terminal_sanity_check (view);
|
||||
|
||||
term_view = view;
|
||||
|
||||
/* Note: currently there is no API for changing the gfxterm font
|
||||
on the fly, so whatever font the initially loaded theme specifies
|
||||
will be permanent. */
|
||||
grub_gfxterm_set_window (GRUB_VIDEO_RENDER_TARGET_DISPLAY,
|
||||
view->terminal_rect.x,
|
||||
view->terminal_rect.y,
|
||||
view->terminal_rect.width,
|
||||
view->terminal_rect.height,
|
||||
view->double_repaint,
|
||||
terminal_font,
|
||||
view->terminal_border);
|
||||
grub_gfxterm_decorator_hook = grub_gfxmenu_draw_terminal_box;
|
||||
}
|
||||
|
||||
static void
|
||||
init_background (grub_gfxmenu_view_t view)
|
||||
{
|
||||
if (view->scaled_desktop_image || (!view->raw_desktop_image))
|
||||
return;
|
||||
|
||||
struct grub_video_bitmap *scaled_bitmap;
|
||||
if (view->desktop_image_scale_method ==
|
||||
GRUB_VIDEO_BITMAP_SELECTION_METHOD_STRETCH)
|
||||
grub_video_bitmap_create_scaled (&scaled_bitmap,
|
||||
view->screen.width,
|
||||
view->screen.height,
|
||||
view->raw_desktop_image,
|
||||
GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST);
|
||||
else
|
||||
grub_video_bitmap_scale_proportional (&scaled_bitmap,
|
||||
view->screen.width,
|
||||
view->screen.height,
|
||||
view->raw_desktop_image,
|
||||
GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST,
|
||||
view->desktop_image_scale_method,
|
||||
view->desktop_image_v_align,
|
||||
view->desktop_image_h_align);
|
||||
if (! scaled_bitmap)
|
||||
return;
|
||||
view->scaled_desktop_image = scaled_bitmap;
|
||||
|
||||
}
|
||||
|
||||
/* FIXME: previously notifications were displayed in special case.
|
||||
Is it necessary?
|
||||
*/
|
||||
#if 0
|
||||
/* Sets MESSAGE as the progress message for the view.
|
||||
MESSAGE can be 0, in which case no message is displayed. */
|
||||
static void
|
||||
set_progress_message (grub_gfxmenu_view_t view, const char *message)
|
||||
{
|
||||
grub_free (view->progress_message_text);
|
||||
if (message)
|
||||
view->progress_message_text = grub_strdup (message);
|
||||
else
|
||||
view->progress_message_text = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
notify_booting (grub_menu_entry_t entry, void *userdata)
|
||||
{
|
||||
grub_gfxmenu_view_t view = (grub_gfxmenu_view_t) userdata;
|
||||
|
||||
char *s = grub_malloc (100 + grub_strlen (entry->title));
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
grub_sprintf (s, "Booting '%s'", entry->title);
|
||||
set_progress_message (view, s);
|
||||
grub_free (s);
|
||||
grub_gfxmenu_view_redraw (view, &view->progress_message_frame);
|
||||
grub_video_swap_buffers ();
|
||||
if (view->double_repaint)
|
||||
grub_gfxmenu_view_redraw (view, &view->progress_message_frame);
|
||||
}
|
||||
|
||||
static void
|
||||
notify_fallback (grub_menu_entry_t entry, void *userdata)
|
||||
{
|
||||
grub_gfxmenu_view_t view = (grub_gfxmenu_view_t) userdata;
|
||||
|
||||
char *s = grub_malloc (100 + grub_strlen (entry->title));
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
grub_sprintf (s, "Falling back to '%s'", entry->title);
|
||||
set_progress_message (view, s);
|
||||
grub_free (s);
|
||||
grub_gfxmenu_view_redraw (view, &view->progress_message_frame);
|
||||
grub_video_swap_buffers ();
|
||||
if (view->double_repaint)
|
||||
grub_gfxmenu_view_redraw (view, &view->progress_message_frame);
|
||||
}
|
||||
|
||||
static void
|
||||
notify_execution_failure (void *userdata __attribute__ ((unused)))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static struct grub_menu_execute_callback execute_callback =
|
||||
{
|
||||
.notify_booting = notify_booting,
|
||||
.notify_fallback = notify_fallback,
|
||||
.notify_failure = notify_execution_failure
|
||||
};
|
||||
|
||||
#endif
|
@@ -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);
|
||||
|
||||
|
1559
GRUB2/MOD_SRC/grub-2.04/grub-core/lib/syslinux_parse.c
Normal file
1585
GRUB2/MOD_SRC/grub-2.04/grub-core/loader/i386/linux.c
Normal file
575
GRUB2/MOD_SRC/grub-2.04/grub-core/normal/main.c
Normal file
@@ -0,0 +1,575 @@
|
||||
/* main.c - the normal mode main routine */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2000,2001,2002,2003,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/kernel.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/menu.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/parser.h>
|
||||
#include <grub/reader.h>
|
||||
#include <grub/menu_viewer.h>
|
||||
#include <grub/auth.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/charset.h>
|
||||
#include <grub/script_sh.h>
|
||||
#include <grub/bufio.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
#define GRUB_DEFAULT_HISTORY_SIZE 50
|
||||
|
||||
static int nested_level = 0;
|
||||
int grub_normal_exit_level = 0;
|
||||
|
||||
void
|
||||
grub_normal_free_menu (grub_menu_t menu)
|
||||
{
|
||||
grub_menu_entry_t entry = menu->entry_list;
|
||||
|
||||
while (entry)
|
||||
{
|
||||
grub_menu_entry_t next_entry = entry->next;
|
||||
grub_size_t i;
|
||||
|
||||
if (entry->classes)
|
||||
{
|
||||
struct grub_menu_entry_class *class;
|
||||
for (class = entry->classes; class; class = class->next)
|
||||
grub_free (class->name);
|
||||
grub_free (entry->classes);
|
||||
}
|
||||
|
||||
if (entry->args)
|
||||
{
|
||||
for (i = 0; entry->args[i]; i++)
|
||||
grub_free (entry->args[i]);
|
||||
grub_free (entry->args);
|
||||
}
|
||||
|
||||
if (entry->bls)
|
||||
{
|
||||
entry->bls->visible = 0;
|
||||
}
|
||||
|
||||
grub_free ((void *) entry->id);
|
||||
grub_free ((void *) entry->users);
|
||||
grub_free ((void *) entry->title);
|
||||
grub_free ((void *) entry->sourcecode);
|
||||
grub_free (entry);
|
||||
entry = next_entry;
|
||||
}
|
||||
|
||||
grub_free (menu);
|
||||
grub_env_unset_menu ();
|
||||
}
|
||||
|
||||
/* Helper for read_config_file. */
|
||||
static grub_err_t
|
||||
read_config_file_getline (char **line, int cont __attribute__ ((unused)),
|
||||
void *data)
|
||||
{
|
||||
grub_file_t file = data;
|
||||
|
||||
while (1)
|
||||
{
|
||||
char *buf;
|
||||
|
||||
*line = buf = grub_file_getline (file);
|
||||
if (! buf)
|
||||
return grub_errno;
|
||||
|
||||
if (buf[0] == '#')
|
||||
grub_free (*line);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_menu_t
|
||||
read_config_file (const char *config)
|
||||
{
|
||||
grub_file_t rawfile, file;
|
||||
char *old_file = 0, *old_dir = 0;
|
||||
char *config_dir, *ptr = 0;
|
||||
const char *ctmp;
|
||||
|
||||
grub_menu_t newmenu;
|
||||
|
||||
newmenu = grub_env_get_menu ();
|
||||
if (! newmenu)
|
||||
{
|
||||
newmenu = grub_zalloc (sizeof (*newmenu));
|
||||
if (! newmenu)
|
||||
return 0;
|
||||
|
||||
grub_env_set_menu (newmenu);
|
||||
}
|
||||
|
||||
/* Try to open the config file. */
|
||||
rawfile = grub_file_open (config, GRUB_FILE_TYPE_CONFIG);
|
||||
if (! rawfile)
|
||||
return 0;
|
||||
|
||||
file = grub_bufio_open (rawfile, 0);
|
||||
if (! file)
|
||||
{
|
||||
grub_file_close (rawfile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctmp = grub_env_get ("config_file");
|
||||
if (ctmp)
|
||||
old_file = grub_strdup (ctmp);
|
||||
ctmp = grub_env_get ("config_directory");
|
||||
if (ctmp)
|
||||
old_dir = grub_strdup (ctmp);
|
||||
if (*config == '(')
|
||||
{
|
||||
grub_env_set ("config_file", config);
|
||||
config_dir = grub_strdup (config);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* $root is guranteed to be defined, otherwise open above would fail */
|
||||
config_dir = grub_xasprintf ("(%s)%s", grub_env_get ("root"), config);
|
||||
if (config_dir)
|
||||
grub_env_set ("config_file", config_dir);
|
||||
}
|
||||
if (config_dir)
|
||||
{
|
||||
ptr = grub_strrchr (config_dir, '/');
|
||||
if (ptr)
|
||||
*ptr = 0;
|
||||
grub_env_set ("config_directory", config_dir);
|
||||
grub_free (config_dir);
|
||||
}
|
||||
|
||||
grub_env_export ("config_file");
|
||||
grub_env_export ("config_directory");
|
||||
|
||||
while (1)
|
||||
{
|
||||
char *line;
|
||||
|
||||
/* Print an error, if any. */
|
||||
grub_print_error ();
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
|
||||
if ((read_config_file_getline (&line, 0, file)) || (! line))
|
||||
break;
|
||||
|
||||
grub_normal_parse_line (line, read_config_file_getline, file);
|
||||
grub_free (line);
|
||||
}
|
||||
|
||||
if (old_file)
|
||||
grub_env_set ("config_file", old_file);
|
||||
else
|
||||
grub_env_unset ("config_file");
|
||||
if (old_dir)
|
||||
grub_env_set ("config_directory", old_dir);
|
||||
else
|
||||
grub_env_unset ("config_directory");
|
||||
grub_free (old_file);
|
||||
grub_free (old_dir);
|
||||
|
||||
grub_file_close (file);
|
||||
|
||||
return newmenu;
|
||||
}
|
||||
|
||||
/* Initialize the screen. */
|
||||
void
|
||||
grub_normal_init_page (struct grub_term_output *term,
|
||||
int y)
|
||||
{
|
||||
grub_ssize_t msg_len;
|
||||
int posx;
|
||||
char *msg_formatted;
|
||||
grub_uint32_t *unicode_msg;
|
||||
grub_uint32_t *last_position;
|
||||
|
||||
grub_term_cls (term);
|
||||
|
||||
msg_formatted = grub_xasprintf (_("GNU GRUB version %s"), PACKAGE_VERSION);
|
||||
if (!msg_formatted)
|
||||
return;
|
||||
|
||||
msg_len = grub_utf8_to_ucs4_alloc (msg_formatted,
|
||||
&unicode_msg, &last_position);
|
||||
grub_free (msg_formatted);
|
||||
|
||||
if (msg_len < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
posx = grub_getstringwidth (unicode_msg, last_position, term);
|
||||
posx = ((int) grub_term_width (term) - posx) / 2;
|
||||
if (posx < 0)
|
||||
posx = 0;
|
||||
grub_term_gotoxy (term, (struct grub_term_coordinate) { posx, y });
|
||||
|
||||
grub_print_ucs4 (unicode_msg, last_position, 0, 0, term);
|
||||
grub_putcode ('\n', term);
|
||||
grub_putcode ('\n', term);
|
||||
grub_free (unicode_msg);
|
||||
}
|
||||
|
||||
static void
|
||||
read_lists (const char *val)
|
||||
{
|
||||
if (! grub_no_modules)
|
||||
{
|
||||
read_command_list (val);
|
||||
read_fs_list (val);
|
||||
read_crypto_list (val);
|
||||
read_terminal_list (val);
|
||||
}
|
||||
grub_gettext_reread_prefix (val);
|
||||
}
|
||||
|
||||
static char *
|
||||
read_lists_hook (struct grub_env_var *var __attribute__ ((unused)),
|
||||
const char *val)
|
||||
{
|
||||
read_lists (val);
|
||||
return val ? grub_strdup (val) : NULL;
|
||||
}
|
||||
|
||||
/* Read the config file CONFIG and execute the menu interface or
|
||||
the command line interface if BATCH is false. */
|
||||
void
|
||||
grub_normal_execute (const char *config, int nested, int batch)
|
||||
{
|
||||
grub_menu_t menu = 0;
|
||||
const char *prefix;
|
||||
|
||||
if (! nested)
|
||||
{
|
||||
prefix = grub_env_get ("prefix");
|
||||
read_lists (prefix);
|
||||
grub_register_variable_hook ("prefix", NULL, read_lists_hook);
|
||||
}
|
||||
|
||||
grub_boot_time ("Executing config file");
|
||||
|
||||
if (config)
|
||||
{
|
||||
menu = read_config_file (config);
|
||||
|
||||
/* Ignore any error. */
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
grub_boot_time ("Executed config file");
|
||||
|
||||
if (! batch)
|
||||
{
|
||||
if (menu && menu->size)
|
||||
{
|
||||
|
||||
grub_boot_time ("Entering menu");
|
||||
grub_show_menu (menu, nested, 0);
|
||||
if (nested)
|
||||
grub_normal_free_menu (menu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This starts the normal mode. */
|
||||
void
|
||||
grub_enter_normal_mode (const char *config)
|
||||
{
|
||||
grub_boot_time ("Entering normal mode");
|
||||
nested_level++;
|
||||
grub_normal_execute (config, 0, 0);
|
||||
grub_boot_time ("Entering shell");
|
||||
grub_cmdline_run (0, 1);
|
||||
nested_level--;
|
||||
if (grub_normal_exit_level)
|
||||
grub_normal_exit_level--;
|
||||
grub_boot_time ("Exiting normal mode");
|
||||
}
|
||||
|
||||
/* Enter normal mode from rescue mode. */
|
||||
static grub_err_t
|
||||
grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
if (argc == 0)
|
||||
{
|
||||
/* Guess the config filename. It is necessary to make CONFIG static,
|
||||
so that it won't get broken by longjmp. */
|
||||
char *config;
|
||||
const char *prefix;
|
||||
|
||||
prefix = grub_env_get ("prefix");
|
||||
if (prefix)
|
||||
{
|
||||
config = grub_xasprintf ("%s/grub.cfg", prefix);
|
||||
if (! config)
|
||||
goto quit;
|
||||
|
||||
grub_enter_normal_mode (config);
|
||||
grub_free (config);
|
||||
}
|
||||
else
|
||||
grub_enter_normal_mode (0);
|
||||
}
|
||||
else
|
||||
grub_enter_normal_mode (argv[0]);
|
||||
|
||||
quit:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Exit from normal mode to rescue mode. */
|
||||
static grub_err_t
|
||||
grub_cmd_normal_exit (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char *argv[] __attribute__ ((unused)))
|
||||
{
|
||||
if (nested_level <= grub_normal_exit_level)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "not in normal environment");
|
||||
grub_normal_exit_level++;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_normal_reader_init (int nested)
|
||||
{
|
||||
struct grub_term_output *term;
|
||||
const char *msg_esc = _("ESC at any time exits.");
|
||||
char *msg_formatted;
|
||||
|
||||
msg_formatted = grub_xasprintf (_("Minimal BASH-like line editing is supported. For "
|
||||
"the first word, TAB lists possible command completions. Anywhere "
|
||||
"else TAB lists possible device or file completions. %s"),
|
||||
nested ? msg_esc : "");
|
||||
if (!msg_formatted)
|
||||
return grub_errno;
|
||||
|
||||
FOR_ACTIVE_TERM_OUTPUTS(term)
|
||||
{
|
||||
grub_normal_init_page (term, 1);
|
||||
grub_term_setcursor (term, 1);
|
||||
|
||||
if (grub_term_width (term) > 3 + STANDARD_MARGIN + 20)
|
||||
grub_print_message_indented (msg_formatted, 3, STANDARD_MARGIN, term);
|
||||
else
|
||||
grub_print_message_indented (msg_formatted, 0, 0, term);
|
||||
grub_putcode ('\n', term);
|
||||
grub_putcode ('\n', term);
|
||||
grub_putcode ('\n', term);
|
||||
}
|
||||
grub_free (msg_formatted);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_normal_read_line_real (char **line, int cont, int nested)
|
||||
{
|
||||
const char *prompt;
|
||||
|
||||
if (cont)
|
||||
/* TRANSLATORS: it's command line prompt. */
|
||||
prompt = _(">");
|
||||
else
|
||||
/* TRANSLATORS: it's command line prompt. */
|
||||
prompt = _("grub>");
|
||||
|
||||
if (!prompt)
|
||||
return grub_errno;
|
||||
|
||||
while (1)
|
||||
{
|
||||
*line = grub_cmdline_get (prompt);
|
||||
if (*line)
|
||||
return 0;
|
||||
|
||||
if (cont || nested)
|
||||
{
|
||||
grub_free (*line);
|
||||
*line = 0;
|
||||
return grub_errno;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_normal_read_line (char **line, int cont,
|
||||
void *data __attribute__ ((unused)))
|
||||
{
|
||||
return grub_normal_read_line_real (line, cont, 0);
|
||||
}
|
||||
|
||||
void
|
||||
grub_cmdline_run (int nested, int force_auth)
|
||||
{
|
||||
grub_err_t err = GRUB_ERR_NONE;
|
||||
|
||||
do
|
||||
{
|
||||
err = grub_auth_check_authentication (NULL);
|
||||
}
|
||||
while (err && force_auth);
|
||||
|
||||
if (err)
|
||||
{
|
||||
grub_print_error ();
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
grub_normal_reader_init (nested);
|
||||
|
||||
while (1)
|
||||
{
|
||||
char *line = NULL;
|
||||
|
||||
if (grub_normal_exit_level)
|
||||
break;
|
||||
|
||||
/* Print an error, if any. */
|
||||
grub_print_error ();
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
|
||||
grub_normal_read_line_real (&line, 0, nested);
|
||||
if (! line)
|
||||
break;
|
||||
|
||||
grub_normal_parse_line (line, grub_normal_read_line, NULL);
|
||||
grub_free (line);
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
grub_env_write_pager (struct grub_env_var *var __attribute__ ((unused)),
|
||||
const char *val)
|
||||
{
|
||||
grub_set_more ((*val == '1'));
|
||||
return grub_strdup (val);
|
||||
}
|
||||
|
||||
/* clear */
|
||||
static grub_err_t
|
||||
grub_mini_cmd_clear (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char *argv[] __attribute__ ((unused)))
|
||||
{
|
||||
grub_cls ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_command_t cmd_clear;
|
||||
|
||||
static void (*grub_xputs_saved) (const char *str);
|
||||
static const char *features[] = {
|
||||
"feature_chainloader_bpb", "feature_ntldr", "feature_platform_search_hint",
|
||||
"feature_default_font_path", "feature_all_video_module",
|
||||
"feature_menuentry_id", "feature_menuentry_options", "feature_200_final",
|
||||
"feature_nativedisk_cmd", "feature_timeout_style"
|
||||
};
|
||||
|
||||
GRUB_MOD_INIT(normal)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
grub_boot_time ("Preparing normal module");
|
||||
|
||||
/* Previously many modules depended on gzio. Be nice to user and load it. */
|
||||
grub_dl_load ("gzio");
|
||||
grub_errno = 0;
|
||||
|
||||
grub_normal_auth_init ();
|
||||
grub_context_init ();
|
||||
grub_script_init ();
|
||||
grub_menu_init ();
|
||||
|
||||
grub_xputs_saved = grub_xputs;
|
||||
grub_xputs = grub_xputs_normal;
|
||||
|
||||
/* Normal mode shouldn't be unloaded. */
|
||||
if (mod)
|
||||
grub_dl_ref (mod);
|
||||
|
||||
cmd_clear =
|
||||
grub_register_command ("clear", grub_mini_cmd_clear,
|
||||
0, N_("Clear the screen."));
|
||||
|
||||
grub_set_history (GRUB_DEFAULT_HISTORY_SIZE);
|
||||
|
||||
grub_register_variable_hook ("pager", 0, grub_env_write_pager);
|
||||
grub_env_export ("pager");
|
||||
|
||||
/* Register a command "normal" for the rescue mode. */
|
||||
grub_register_command ("normal", grub_cmd_normal,
|
||||
0, N_("Enter normal mode."));
|
||||
grub_register_command ("normal_exit", grub_cmd_normal_exit,
|
||||
0, N_("Exit from normal mode."));
|
||||
|
||||
/* Reload terminal colors when these variables are written to. */
|
||||
grub_register_variable_hook ("color_normal", NULL, grub_env_write_color_normal);
|
||||
grub_register_variable_hook ("color_highlight", NULL, grub_env_write_color_highlight);
|
||||
|
||||
/* Preserve hooks after context changes. */
|
||||
grub_env_export ("color_normal");
|
||||
grub_env_export ("color_highlight");
|
||||
|
||||
/* Set default color names. */
|
||||
grub_env_set ("color_normal", "light-gray/black");
|
||||
grub_env_set ("color_highlight", "black/light-gray");
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE (features); i++)
|
||||
{
|
||||
grub_env_set (features[i], "y");
|
||||
grub_env_export (features[i]);
|
||||
}
|
||||
grub_env_set ("grub_cpu", GRUB_TARGET_CPU);
|
||||
grub_env_export ("grub_cpu");
|
||||
grub_env_set ("grub_platform", GRUB_PLATFORM);
|
||||
grub_env_export ("grub_platform");
|
||||
|
||||
grub_boot_time ("Normal module prepared");
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(normal)
|
||||
{
|
||||
grub_context_fini ();
|
||||
grub_script_fini ();
|
||||
grub_menu_fini ();
|
||||
grub_normal_auth_fini ();
|
||||
|
||||
grub_xputs = grub_xputs_saved;
|
||||
|
||||
grub_set_history (0);
|
||||
grub_register_variable_hook ("pager", 0, 0);
|
||||
grub_fs_autoload_hook = 0;
|
||||
grub_unregister_command (cmd_clear);
|
||||
}
|
@@ -803,6 +803,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
|
||||
goto refresh;
|
||||
|
||||
case GRUB_TERM_KEY_F2:
|
||||
case '2':
|
||||
if (0 == g_ventoy_fn_mutex) {
|
||||
cmdstr = grub_env_get("VTOY_F2_CMD");
|
||||
if (cmdstr)
|
||||
@@ -816,6 +817,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
|
||||
}
|
||||
break;
|
||||
case GRUB_TERM_KEY_F3:
|
||||
case '3':
|
||||
if (0 == g_ventoy_fn_mutex) {
|
||||
cmdstr = grub_env_get("VTOY_F3_CMD");
|
||||
if (cmdstr)
|
||||
@@ -827,6 +829,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
|
||||
}
|
||||
break;
|
||||
case GRUB_TERM_KEY_F4:
|
||||
case '4':
|
||||
if (0 == g_ventoy_fn_mutex) {
|
||||
cmdstr = grub_env_get("VTOY_F4_CMD");
|
||||
if (cmdstr)
|
||||
@@ -840,6 +843,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
|
||||
}
|
||||
break;
|
||||
case GRUB_TERM_KEY_F5:
|
||||
case '5':
|
||||
if (0 == g_ventoy_fn_mutex) {
|
||||
cmdstr = grub_env_get("VTOY_F5_CMD");
|
||||
if (cmdstr)
|
||||
@@ -853,6 +857,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
|
||||
}
|
||||
break;
|
||||
case GRUB_TERM_KEY_F6:
|
||||
case '6':
|
||||
if (0 == g_ventoy_fn_mutex) {
|
||||
cmdstr = grub_env_get("VTOY_F6_CMD");
|
||||
if (cmdstr)
|
||||
@@ -866,6 +871,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
|
||||
}
|
||||
break;
|
||||
case GRUB_TERM_KEY_F7:
|
||||
case '7':
|
||||
cmdstr = grub_env_get("VTOY_F7_CMD");
|
||||
if (cmdstr)
|
||||
{
|
||||
@@ -875,6 +881,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
|
||||
}
|
||||
break;
|
||||
case GRUB_TERM_KEY_F1:
|
||||
case '1':
|
||||
menu_fini ();
|
||||
g_ventoy_memdisk_mode = 1 - g_ventoy_memdisk_mode;
|
||||
g_ventoy_menu_refresh = 1;
|
||||
@@ -992,6 +999,9 @@ show_menu (grub_menu_t menu, int nested, int autobooted)
|
||||
grub_menu_execute_entry (e, 0);
|
||||
if (autobooted)
|
||||
break;
|
||||
|
||||
if (2 == e->argc && e->args && e->args[1] && grub_strncmp(e->args[1], "VTOY_RUN_RET", 12) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
|
@@ -180,22 +180,31 @@ command-line or ESC to discard edits and return to the GRUB menu."),
|
||||
|
||||
if (nested)
|
||||
{
|
||||
#if 0
|
||||
ret += grub_print_message_indented_real
|
||||
(_("Press enter to boot the selected OS, "
|
||||
"`e' to edit the commands before booting "
|
||||
"or `c' for a command-line. ESC to return previous menu."),
|
||||
STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
char szLine[128];
|
||||
const char *checkret = grub_env_get("VTOY_CHKDEV_RESULT_STRING");
|
||||
if (checkret == NULL || checkret[0] != '0') {
|
||||
grub_snprintf(szLine, sizeof(szLine), "%s [Unofficial Ventoy]", grub_env_get("VTOY_TEXT_MENU_VER"));
|
||||
} else {
|
||||
grub_snprintf(szLine, sizeof(szLine), "%s", grub_env_get("VTOY_TEXT_MENU_VER"));
|
||||
}
|
||||
|
||||
ret += grub_print_message_indented_real("\n", STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
|
||||
|
||||
ret += grub_print_message_indented_real(grub_env_get("VTOY_TEXT_MENU_VER"),
|
||||
STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
|
||||
ret += grub_print_message_indented_real(szLine, STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
|
||||
|
||||
ret += grub_print_message_indented_real("\n", STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
|
||||
ret += grub_print_message_indented_real(grub_env_get("VTOY_HOTKEY_TIP"),
|
||||
STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
|
||||
3, 6, term, dry_run);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
@@ -23,10 +23,14 @@
|
||||
|
||||
#define VTOY_MAX_SCRIPT_BUF (4 * 1024 * 1024)
|
||||
|
||||
#define VTOY_PART_BUF_LEN (128 * 1024)
|
||||
|
||||
#define VTOY_FILT_MIN_FILE_SIZE 32768
|
||||
|
||||
#define VTOY_SIZE_1GB 1073741824
|
||||
#define VTOY_SIZE_512KB (512 * 1024)
|
||||
#define VTOY_SIZE_1MB (1024 * 1024)
|
||||
#define VTOY_SIZE_512KB (512 * 1024)
|
||||
#define VTOY_SIZE_1KB 1024
|
||||
|
||||
#define JSON_SUCCESS 0
|
||||
#define JSON_FAILED 1
|
||||
@@ -46,6 +50,8 @@
|
||||
#define ventoy_get_env(key) ventoy_env_op1(get, key)
|
||||
#define ventoy_set_env(key, val) ventoy_env_op2(set, key, val)
|
||||
|
||||
#define VTOY_WARNING "!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!"
|
||||
|
||||
typedef struct ventoy_initrd_ctx
|
||||
{
|
||||
const char *path_prefix;
|
||||
@@ -97,6 +103,18 @@ typedef int (*grub_char_check_func)(int c);
|
||||
#define ventoy_is_decimal(str) ventoy_string_check(str, grub_isdigit)
|
||||
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct ventoy_patch_vhd
|
||||
{
|
||||
grub_uint8_t part_offset_or_guid[16];
|
||||
grub_uint32_t reserved1;
|
||||
grub_uint32_t part_type;
|
||||
grub_uint8_t disk_signature_or_guid[16];
|
||||
grub_uint8_t reserved2[16];
|
||||
grub_uint8_t vhd_file_path[1];
|
||||
}ventoy_patch_vhd;
|
||||
#pragma pack()
|
||||
|
||||
// El Torito Boot Record Volume Descriptor
|
||||
#pragma pack(1)
|
||||
typedef struct eltorito_descriptor
|
||||
@@ -123,12 +141,24 @@ typedef struct ventoy_udf_override
|
||||
grub_uint32_t position;
|
||||
}ventoy_udf_override;
|
||||
|
||||
typedef struct ventoy_iso9660_vd
|
||||
{
|
||||
grub_uint8_t type;
|
||||
grub_uint8_t id[5];
|
||||
grub_uint8_t ver;
|
||||
grub_uint8_t res;
|
||||
char sys[32];
|
||||
char vol[32];
|
||||
}ventoy_iso9660_vd;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
#define img_type_iso 0
|
||||
#define img_type_wim 1
|
||||
#define img_type_efi 2
|
||||
#define img_type_img 3
|
||||
#define img_type_iso 0
|
||||
#define img_type_wim 1
|
||||
#define img_type_efi 2
|
||||
#define img_type_img 3
|
||||
#define img_type_vhd 4
|
||||
#define img_type_vtoy 5
|
||||
|
||||
typedef struct img_info
|
||||
{
|
||||
@@ -457,6 +487,8 @@ grub_err_t ventoy_cmd_linux_locate_initrd(grub_extcmd_context_t ctxt, int argc,
|
||||
grub_err_t ventoy_cmd_initrd_count(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_valid_initrd_count(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_cpio_busybox_64(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_trailer_cpio(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
int ventoy_cpio_newc_fill_head(void *buf, int filesize, const void *filedata, const char *name);
|
||||
grub_file_t ventoy_grub_file_open(enum grub_file_type type, const char *fmt, ...);
|
||||
grub_uint64_t ventoy_grub_get_file_size(const char *fmt, ...);
|
||||
@@ -590,8 +622,88 @@ typedef struct ventoy_mbr_head
|
||||
grub_uint8_t Byte55;
|
||||
grub_uint8_t ByteAA;
|
||||
}ventoy_mbr_head;
|
||||
|
||||
typedef struct ventoy_gpt_head
|
||||
{
|
||||
char Signature[8]; /* EFI PART */
|
||||
grub_uint8_t Version[4];
|
||||
grub_uint32_t Length;
|
||||
grub_uint32_t Crc;
|
||||
grub_uint8_t Reserved1[4];
|
||||
grub_uint64_t EfiStartLBA;
|
||||
grub_uint64_t EfiBackupLBA;
|
||||
grub_uint64_t PartAreaStartLBA;
|
||||
grub_uint64_t PartAreaEndLBA;
|
||||
grub_uint8_t DiskGuid[16];
|
||||
grub_uint64_t PartTblStartLBA;
|
||||
grub_uint32_t PartTblTotNum;
|
||||
grub_uint32_t PartTblEntryLen;
|
||||
grub_uint32_t PartTblCrc;
|
||||
grub_uint8_t Reserved2[420];
|
||||
}ventoy_gpt_head;
|
||||
|
||||
typedef struct ventoy_gpt_part_tbl
|
||||
{
|
||||
grub_uint8_t PartType[16];
|
||||
grub_uint8_t PartGuid[16];
|
||||
grub_uint64_t StartLBA;
|
||||
grub_uint64_t LastLBA;
|
||||
grub_uint64_t Attr;
|
||||
grub_uint16_t Name[36];
|
||||
}ventoy_gpt_part_tbl;
|
||||
|
||||
typedef struct ventoy_gpt_info
|
||||
{
|
||||
ventoy_mbr_head MBR;
|
||||
ventoy_gpt_head Head;
|
||||
ventoy_gpt_part_tbl PartTbl[128];
|
||||
}ventoy_gpt_info;
|
||||
|
||||
typedef struct vhd_footer_t
|
||||
{
|
||||
char cookie[8]; // Cookie
|
||||
grub_uint32_t features; // Features
|
||||
grub_uint32_t ffversion; // File format version
|
||||
grub_uint32_t dataoffset; // Data offset
|
||||
grub_uint32_t timestamp; // Timestamp
|
||||
grub_uint32_t creatorapp; // Creator application
|
||||
grub_uint32_t creatorver; // Creator version
|
||||
grub_uint32_t creatorhos; // Creator host OS
|
||||
grub_uint32_t origsize; // Original size
|
||||
grub_uint32_t currsize; // Current size
|
||||
grub_uint32_t diskgeom; // Disk geometry
|
||||
grub_uint32_t disktype; // Disk type
|
||||
grub_uint32_t checksum; // Checksum
|
||||
grub_uint8_t uniqueid[16]; // Unique ID
|
||||
grub_uint8_t savedst; // Saved state
|
||||
}vhd_footer_t;
|
||||
|
||||
#define VDI_IMAGE_FILE_INFO "<<< Oracle VM VirtualBox Disk Image >>>\n"
|
||||
|
||||
/** Image signature. */
|
||||
#define VDI_IMAGE_SIGNATURE (0xbeda107f)
|
||||
|
||||
typedef struct VDIPREHEADER
|
||||
{
|
||||
/** Just text info about image type, for eyes only. */
|
||||
char szFileInfo[64];
|
||||
/** The image signature (VDI_IMAGE_SIGNATURE). */
|
||||
grub_uint32_t u32Signature;
|
||||
/** The image version (VDI_IMAGE_VERSION). */
|
||||
grub_uint32_t u32Version;
|
||||
} VDIPREHEADER, *PVDIPREHEADER;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
typedef struct ventoy_video_mode
|
||||
{
|
||||
grub_uint32_t width;
|
||||
grub_uint32_t height;
|
||||
grub_uint32_t bpp;
|
||||
}ventoy_video_mode;
|
||||
|
||||
|
||||
|
||||
typedef struct file_fullpath
|
||||
{
|
||||
char path[256];
|
||||
@@ -658,6 +770,14 @@ typedef struct injection_config
|
||||
struct injection_config *next;
|
||||
}injection_config;
|
||||
|
||||
typedef struct auto_memdisk
|
||||
{
|
||||
int pathlen;
|
||||
char isopath[256];
|
||||
|
||||
struct auto_memdisk *next;
|
||||
}auto_memdisk;
|
||||
|
||||
extern int g_ventoy_menu_esc;
|
||||
extern int g_ventoy_suppress_esc;
|
||||
extern int g_ventoy_last_entry;
|
||||
@@ -666,7 +786,26 @@ extern int g_ventoy_iso_raw;
|
||||
extern int g_ventoy_iso_uefi_drv;
|
||||
extern int g_ventoy_case_insensitive;
|
||||
extern grub_uint8_t g_ventoy_chain_type;
|
||||
extern int g_vhdboot_enable;
|
||||
extern ventoy_gpt_info *g_ventoy_part_info;
|
||||
|
||||
#define ventoy_unix_fill_virt(new_data, new_len) \
|
||||
{ \
|
||||
data_secs = (new_len + 2047) / 2048; \
|
||||
cur->mem_sector_start = sector; \
|
||||
cur->mem_sector_end = cur->mem_sector_start + data_secs; \
|
||||
cur->mem_sector_offset = offset; \
|
||||
cur->remap_sector_start = 0; \
|
||||
cur->remap_sector_end = 0; \
|
||||
cur->org_sector_start = 0; \
|
||||
grub_memcpy(override + offset, new_data, new_len); \
|
||||
cur++; \
|
||||
sector += data_secs; \
|
||||
offset += new_len; \
|
||||
chain->virt_img_size_in_bytes += data_secs * 2048; \
|
||||
}
|
||||
|
||||
char * ventoy_get_line(char *start);
|
||||
int ventoy_cmp_img(img_info *img1, img_info *img2);
|
||||
void ventoy_swap_img(img_info *img1, img_info *img2);
|
||||
char * ventoy_plugin_get_cur_install_template(const char *isopath);
|
||||
@@ -679,6 +818,7 @@ int ventoy_plugin_get_persistent_chunklist(const char *isopath, int index, vento
|
||||
const char * ventoy_plugin_get_injection(const char *isopath);
|
||||
const char * ventoy_plugin_get_menu_alias(int type, const char *isopath);
|
||||
const char * ventoy_plugin_get_menu_class(int type, const char *name);
|
||||
int ventoy_plugin_check_memdisk(const char *isopath);
|
||||
int ventoy_get_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist, grub_disk_addr_t start);
|
||||
int ventoy_check_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist, grub_disk_addr_t start);
|
||||
void ventoy_plugin_dump_persistence(void);
|
||||
@@ -687,6 +827,20 @@ grub_err_t ventoy_cmd_linux_get_main_initrd_index(grub_extcmd_context_t ctxt, in
|
||||
grub_err_t ventoy_cmd_collect_wim_patch(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_wim_patch_count(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_locate_wim_patch(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_unix_chain_data(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
int ventoy_get_disk_guid(const char *filename, grub_uint8_t *guid, grub_uint8_t *signature);
|
||||
grub_err_t ventoy_cmd_unix_reset(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_unix_replace_conf(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_unix_replace_ko(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_unix_freebsd_ver(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_parse_freenas_ver(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
int ventoy_check_device_result(int ret);
|
||||
int ventoy_check_device(grub_device_t dev);
|
||||
void ventoy_debug_dump_guid(const char *prefix, grub_uint8_t *guid);
|
||||
grub_err_t ventoy_cmd_load_vhdboot(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_patch_vhdboot(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_raw_chain_data(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
grub_err_t ventoy_cmd_get_vtoy_type(grub_extcmd_context_t ctxt, int argc, char **args);
|
||||
|
||||
#endif /* __VENTOY_DEF_H__ */
|
||||
|
||||
|
@@ -38,8 +38,7 @@
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
|
||||
static char * ventoy_get_line(char *start)
|
||||
char * ventoy_get_line(char *start)
|
||||
{
|
||||
if (start == NULL)
|
||||
{
|
||||
@@ -565,6 +564,14 @@ grub_err_t ventoy_cmd_specify_initrd_file(grub_extcmd_context_t ctxt, int argc,
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
||||
static int ventoy_cpio_newc_get_int(char *value)
|
||||
{
|
||||
char buf[16] = {0};
|
||||
|
||||
grub_memcpy(buf, value, 8);
|
||||
return (int)grub_strtoul(buf, NULL, 16);
|
||||
}
|
||||
|
||||
static void ventoy_cpio_newc_fill_int(grub_uint32_t value, char *buf, int buflen)
|
||||
{
|
||||
int i;
|
||||
@@ -903,6 +910,53 @@ grub_err_t ventoy_cmd_linux_locate_initrd(grub_extcmd_context_t ctxt, int argc,
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
||||
static int ventoy_cpio_busybox64(cpio_newc_header *head)
|
||||
{
|
||||
char *name;
|
||||
int namelen;
|
||||
int offset;
|
||||
int count = 0;
|
||||
|
||||
name = (char *)(head + 1);
|
||||
while (name[0] && count < 2)
|
||||
{
|
||||
if (grub_strcmp(name, "ventoy/busybox/ash") == 0)
|
||||
{
|
||||
grub_memcpy(name, "ventoy/busybox/32h", 18);
|
||||
count++;
|
||||
}
|
||||
else if (grub_strcmp(name, "ventoy/busybox/64h") == 0)
|
||||
{
|
||||
grub_memcpy(name, "ventoy/busybox/ash", 18);
|
||||
count++;
|
||||
}
|
||||
|
||||
namelen = ventoy_cpio_newc_get_int(head->c_namesize);
|
||||
offset = sizeof(cpio_newc_header) + namelen;
|
||||
offset = ventoy_align(offset, 4);
|
||||
offset += ventoy_cpio_newc_get_int(head->c_filesize);
|
||||
offset = ventoy_align(offset, 4);
|
||||
|
||||
head = (cpio_newc_header *)((char *)head + offset);
|
||||
name = (char *)(head + 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
grub_err_t ventoy_cmd_cpio_busybox_64(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
(void)ctxt;
|
||||
(void)argc;
|
||||
(void)args;
|
||||
|
||||
debug("ventoy_cmd_busybox_64 %d\n", argc);
|
||||
ventoy_cpio_busybox64((cpio_newc_header *)g_ventoy_cpio_buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
grub_err_t ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
int rc;
|
||||
@@ -927,7 +981,7 @@ grub_err_t ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **arg
|
||||
(void)ctxt;
|
||||
(void)argc;
|
||||
|
||||
if (argc != 3)
|
||||
if (argc != 4)
|
||||
{
|
||||
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s cpiofile\n", cmd_raw_name);
|
||||
}
|
||||
@@ -1080,6 +1134,102 @@ grub_err_t ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **arg
|
||||
|
||||
grub_file_close(file);
|
||||
|
||||
if (grub_strcmp(args[3], "busybox=64") == 0)
|
||||
{
|
||||
debug("cpio busybox proc %s\n", args[3]);
|
||||
ventoy_cpio_busybox64((cpio_newc_header *)g_ventoy_cpio_buf);
|
||||
}
|
||||
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_trailer_cpio(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
int mod;
|
||||
int bufsize;
|
||||
int namelen;
|
||||
int offset;
|
||||
char *name;
|
||||
grub_uint8_t *bufend;
|
||||
cpio_newc_header *head;
|
||||
grub_file_t file;
|
||||
char value[64];
|
||||
const grub_uint8_t trailler[124] = {
|
||||
0x30, 0x37, 0x30, 0x37, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30,
|
||||
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||
0x30, 0x30, 0x30, 0x30, 0x30, 0x42, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x54, 0x52,
|
||||
0x41, 0x49, 0x4C, 0x45, 0x52, 0x21, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
(void)ctxt;
|
||||
(void)argc;
|
||||
|
||||
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", args[0], args[1]);
|
||||
if (!file)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
grub_memset(g_ventoy_runtime_buf, 0, sizeof(ventoy_os_param));
|
||||
ventoy_fill_os_param(file, (ventoy_os_param *)g_ventoy_runtime_buf);
|
||||
|
||||
grub_file_close(file);
|
||||
|
||||
grub_memcpy(g_ventoy_initrd_head, trailler, sizeof(trailler));
|
||||
bufend = (grub_uint8_t *)g_ventoy_initrd_head + sizeof(trailler);
|
||||
|
||||
bufsize = (int)(bufend - g_ventoy_cpio_buf);
|
||||
mod = bufsize % 512;
|
||||
if (mod)
|
||||
{
|
||||
grub_memset(bufend, 0, 512 - mod);
|
||||
bufsize += 512 - mod;
|
||||
}
|
||||
|
||||
if (argc > 1 && grub_strcmp(args[2], "noinit") == 0)
|
||||
{
|
||||
head = (cpio_newc_header *)g_ventoy_cpio_buf;
|
||||
name = (char *)(head + 1);
|
||||
|
||||
while (grub_strcmp(name, "TRAILER!!!"))
|
||||
{
|
||||
if (grub_strcmp(name, "init") == 0)
|
||||
{
|
||||
grub_memcpy(name, "xxxx", 4);
|
||||
}
|
||||
else if (grub_strcmp(name, "linuxrc") == 0)
|
||||
{
|
||||
grub_memcpy(name, "vtoyxrc", 7);
|
||||
}
|
||||
else if (grub_strcmp(name, "sbin") == 0)
|
||||
{
|
||||
grub_memcpy(name, "vtoy", 4);
|
||||
}
|
||||
else if (grub_strcmp(name, "sbin/init") == 0)
|
||||
{
|
||||
grub_memcpy(name, "vtoy/vtoy", 9);
|
||||
}
|
||||
|
||||
namelen = ventoy_cpio_newc_get_int(head->c_namesize);
|
||||
offset = sizeof(cpio_newc_header) + namelen;
|
||||
offset = ventoy_align(offset, 4);
|
||||
offset += ventoy_cpio_newc_get_int(head->c_filesize);
|
||||
offset = ventoy_align(offset, 4);
|
||||
|
||||
head = (cpio_newc_header *)((char *)head + offset);
|
||||
name = (char *)(head + 1);
|
||||
}
|
||||
}
|
||||
|
||||
grub_snprintf(value, sizeof(value), "0x%llx", (ulonglong)(ulong)g_ventoy_cpio_buf);
|
||||
ventoy_set_env("ventoy_cpio_addr", value);
|
||||
grub_snprintf(value, sizeof(value), "%d", bufsize);
|
||||
ventoy_set_env("ventoy_cpio_size", value);
|
||||
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
||||
|
@@ -45,6 +45,7 @@ static persistence_config *g_persistence_head = NULL;
|
||||
static menu_alias *g_menu_alias_head = NULL;
|
||||
static menu_class *g_menu_class_head = NULL;
|
||||
static injection_config *g_injection_head = NULL;
|
||||
static auto_memdisk *g_auto_memdisk_head = NULL;
|
||||
|
||||
static int ventoy_plugin_control_check(VTOY_JSON *json, const char *isodisk)
|
||||
{
|
||||
@@ -151,6 +152,12 @@ static int ventoy_plugin_theme_check(VTOY_JSON *json, const char *isodisk)
|
||||
grub_printf("display_mode: %s\n", value);
|
||||
}
|
||||
|
||||
value = vtoy_json_get_string_ex(json->pstChild, "serial_param");
|
||||
if (value)
|
||||
{
|
||||
grub_printf("serial_param %s\n", value);
|
||||
}
|
||||
|
||||
value = vtoy_json_get_string_ex(json->pstChild, "ventoy_left");
|
||||
if (value)
|
||||
{
|
||||
@@ -236,6 +243,13 @@ static int ventoy_plugin_theme_entry(VTOY_JSON *json, const char *isodisk)
|
||||
debug("display_mode %s\n", value);
|
||||
grub_env_set("vtoy_display_mode", value);
|
||||
}
|
||||
|
||||
value = vtoy_json_get_string_ex(json->pstChild, "serial_param");
|
||||
if (value)
|
||||
{
|
||||
debug("serial_param %s\n", value);
|
||||
grub_env_set("vtoy_serial_param", value);
|
||||
}
|
||||
|
||||
value = vtoy_json_get_string_ex(json->pstChild, "ventoy_left");
|
||||
if (value)
|
||||
@@ -997,6 +1011,83 @@ static int ventoy_plugin_menuclass_check(VTOY_JSON *json, const char *isodisk)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ventoy_plugin_auto_memdisk_entry(VTOY_JSON *json, const char *isodisk)
|
||||
{
|
||||
VTOY_JSON *pNode = NULL;
|
||||
auto_memdisk *node = NULL;
|
||||
auto_memdisk *next = NULL;
|
||||
|
||||
(void)isodisk;
|
||||
|
||||
if (json->enDataType != JSON_TYPE_ARRAY)
|
||||
{
|
||||
debug("Not array %d\n", json->enDataType);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (g_auto_memdisk_head)
|
||||
{
|
||||
for (node = g_auto_memdisk_head; node; node = next)
|
||||
{
|
||||
next = node->next;
|
||||
grub_free(node);
|
||||
}
|
||||
|
||||
g_auto_memdisk_head = NULL;
|
||||
}
|
||||
|
||||
for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
|
||||
{
|
||||
if (pNode->enDataType == JSON_TYPE_STRING)
|
||||
{
|
||||
node = grub_zalloc(sizeof(auto_memdisk));
|
||||
if (node)
|
||||
{
|
||||
node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", pNode->unData.pcStrVal);
|
||||
|
||||
if (g_auto_memdisk_head)
|
||||
{
|
||||
node->next = g_auto_memdisk_head;
|
||||
}
|
||||
|
||||
g_auto_memdisk_head = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ventoy_plugin_auto_memdisk_check(VTOY_JSON *json, const char *isodisk)
|
||||
{
|
||||
VTOY_JSON *pNode = NULL;
|
||||
|
||||
if (json->enDataType != JSON_TYPE_ARRAY)
|
||||
{
|
||||
grub_printf("Not array %d\n", json->enDataType);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
|
||||
{
|
||||
if (pNode->enDataType == JSON_TYPE_STRING)
|
||||
{
|
||||
grub_printf("<%s> ", pNode->unData.pcStrVal);
|
||||
|
||||
if (ventoy_check_file_exist("%s%s", isodisk, pNode->unData.pcStrVal))
|
||||
{
|
||||
grub_printf(" [OK]\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_printf(" [NOT EXIST]\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static plugin_entry g_plugin_entries[] =
|
||||
{
|
||||
{ "control", ventoy_plugin_control_entry, ventoy_plugin_control_check },
|
||||
@@ -1006,6 +1097,7 @@ static plugin_entry g_plugin_entries[] =
|
||||
{ "menu_alias", ventoy_plugin_menualias_entry, ventoy_plugin_menualias_check },
|
||||
{ "menu_class", ventoy_plugin_menuclass_entry, ventoy_plugin_menuclass_check },
|
||||
{ "injection", ventoy_plugin_injection_entry, ventoy_plugin_injection_check },
|
||||
{ "auto_memdisk", ventoy_plugin_auto_memdisk_entry, ventoy_plugin_auto_memdisk_check },
|
||||
};
|
||||
|
||||
static int ventoy_parse_plugin_config(VTOY_JSON *json, const char *isodisk)
|
||||
@@ -1150,9 +1242,15 @@ void ventoy_plugin_dump_persistence(void)
|
||||
|
||||
install_template * ventoy_plugin_find_install_template(const char *isopath)
|
||||
{
|
||||
int len;
|
||||
install_template *node = NULL;
|
||||
int len = (int)grub_strlen(isopath);
|
||||
|
||||
|
||||
if (!g_install_template_head)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
len = (int)grub_strlen(isopath);
|
||||
for (node = g_install_template_head; node; node = node->next)
|
||||
{
|
||||
if (node->pathlen == len && grub_strcmp(node->isopath, isopath) == 0)
|
||||
@@ -1184,9 +1282,15 @@ char * ventoy_plugin_get_cur_install_template(const char *isopath)
|
||||
|
||||
persistence_config * ventoy_plugin_find_persistent(const char *isopath)
|
||||
{
|
||||
int len;
|
||||
persistence_config *node = NULL;
|
||||
int len = (int)grub_strlen(isopath);
|
||||
|
||||
|
||||
if (!g_persistence_head)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
len = (int)grub_strlen(isopath);
|
||||
for (node = g_persistence_head; node; node = node->next)
|
||||
{
|
||||
if ((len == node->pathlen) && (grub_strcmp(node->isopath, isopath) == 0))
|
||||
@@ -1259,9 +1363,15 @@ end:
|
||||
|
||||
const char * ventoy_plugin_get_injection(const char *isopath)
|
||||
{
|
||||
int len;
|
||||
injection_config *node = NULL;
|
||||
int len = (int)grub_strlen(isopath);
|
||||
|
||||
if (!g_injection_head)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
len = (int)grub_strlen(isopath);
|
||||
for (node = g_injection_head; node; node = node->next)
|
||||
{
|
||||
if (node->pathlen == len && grub_strcmp(node->isopath, isopath) == 0)
|
||||
@@ -1275,9 +1385,15 @@ const char * ventoy_plugin_get_injection(const char *isopath)
|
||||
|
||||
const char * ventoy_plugin_get_menu_alias(int type, const char *isopath)
|
||||
{
|
||||
int len;
|
||||
menu_alias *node = NULL;
|
||||
int len = (int)grub_strlen(isopath);
|
||||
|
||||
if (!g_menu_alias_head)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
len = (int)grub_strlen(isopath);
|
||||
for (node = g_menu_alias_head; node; node = node->next)
|
||||
{
|
||||
if (node->type == type && node->pathlen &&
|
||||
@@ -1292,9 +1408,16 @@ const char * ventoy_plugin_get_menu_alias(int type, const char *isopath)
|
||||
|
||||
const char * ventoy_plugin_get_menu_class(int type, const char *name)
|
||||
{
|
||||
int len;
|
||||
menu_class *node = NULL;
|
||||
int len = (int)grub_strlen(name);
|
||||
|
||||
if (!g_menu_class_head)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
len = (int)grub_strlen(name);
|
||||
|
||||
if (vtoy_class_image_file == type)
|
||||
{
|
||||
for (node = g_menu_class_head; node; node = node->next)
|
||||
@@ -1319,6 +1442,28 @@ const char * ventoy_plugin_get_menu_class(int type, const char *name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int ventoy_plugin_check_memdisk(const char *isopath)
|
||||
{
|
||||
int len;
|
||||
auto_memdisk *node = NULL;
|
||||
|
||||
if (!g_auto_memdisk_head)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = (int)grub_strlen(isopath);
|
||||
for (node = g_auto_memdisk_head; node; node = node->next)
|
||||
{
|
||||
if (node->pathlen == len && grub_strncmp(isopath, node->isopath, len) == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_plugin_check_json(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
int i = 0;
|
||||
|
633
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_unix.c
Normal file
@@ -0,0 +1,633 @@
|
||||
/******************************************************************************
|
||||
* ventoy_unix.c
|
||||
*
|
||||
* Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#include <grub/types.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/device.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/partition.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/datetime.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/net.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/ventoy.h>
|
||||
#include "ventoy_def.h"
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
char g_ko_mod_path[256];
|
||||
int g_conf_new_len = 0;
|
||||
char *g_conf_new_data = NULL;
|
||||
|
||||
int g_mod_new_len = 0;
|
||||
char *g_mod_new_data = NULL;
|
||||
|
||||
grub_uint64_t g_mod_override_offset = 0;
|
||||
grub_uint64_t g_conf_override_offset = 0;
|
||||
|
||||
static int ventoy_get_file_override(const char *filename, grub_uint64_t *offset)
|
||||
{
|
||||
grub_file_t file;
|
||||
|
||||
*offset = 0;
|
||||
|
||||
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "(loop)%s", filename);
|
||||
if (!file)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
*offset = grub_iso9660_get_last_file_dirent_pos(file) + 2;
|
||||
|
||||
grub_file_close(file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_uint32_t ventoy_unix_get_override_chunk_count(void)
|
||||
{
|
||||
grub_uint32_t count = 0;
|
||||
|
||||
if (g_conf_new_len > 0)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
if (g_mod_new_len > 0)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static grub_uint32_t ventoy_unix_get_virt_chunk_count(void)
|
||||
{
|
||||
grub_uint32_t count = 0;
|
||||
|
||||
if (g_conf_new_len > 0)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
if (g_mod_new_len > 0)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
static grub_uint32_t ventoy_unix_get_virt_chunk_size(void)
|
||||
{
|
||||
grub_uint32_t size;
|
||||
|
||||
size = sizeof(ventoy_virt_chunk) * ventoy_unix_get_virt_chunk_count();
|
||||
|
||||
if (g_conf_new_len > 0)
|
||||
{
|
||||
size += ventoy_align_2k(g_conf_new_len);
|
||||
}
|
||||
|
||||
if (g_mod_new_len > 0)
|
||||
{
|
||||
size += ventoy_align_2k(g_mod_new_len);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static void ventoy_unix_fill_override_data( grub_uint64_t isosize, void *override)
|
||||
{
|
||||
grub_uint64_t sector;
|
||||
ventoy_override_chunk *cur;
|
||||
ventoy_iso9660_override *dirent;
|
||||
|
||||
sector = (isosize + 2047) / 2048;
|
||||
|
||||
cur = (ventoy_override_chunk *)override;
|
||||
|
||||
if (g_conf_new_len > 0)
|
||||
{
|
||||
/* loader.conf */
|
||||
cur->img_offset = g_conf_override_offset;
|
||||
cur->override_size = sizeof(ventoy_iso9660_override);
|
||||
dirent = (ventoy_iso9660_override *)cur->override_data;
|
||||
dirent->first_sector = (grub_uint32_t)sector;
|
||||
dirent->size = (grub_uint32_t)g_conf_new_len;
|
||||
dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector);
|
||||
dirent->size_be = grub_swap_bytes32(dirent->size);
|
||||
sector += (dirent->size + 2047) / 2048;
|
||||
}
|
||||
|
||||
if (g_mod_new_len > 0)
|
||||
{
|
||||
/* mod.ko */
|
||||
cur++;
|
||||
cur->img_offset = g_mod_override_offset;
|
||||
cur->override_size = sizeof(ventoy_iso9660_override);
|
||||
dirent = (ventoy_iso9660_override *)cur->override_data;
|
||||
dirent->first_sector = (grub_uint32_t)sector;
|
||||
dirent->size = (grub_uint32_t)g_mod_new_len;
|
||||
dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector);
|
||||
dirent->size_be = grub_swap_bytes32(dirent->size);
|
||||
sector += (dirent->size + 2047) / 2048;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void ventoy_unix_fill_virt_data( grub_uint64_t isosize, ventoy_chain_head *chain)
|
||||
{
|
||||
grub_uint64_t sector;
|
||||
grub_uint32_t offset;
|
||||
grub_uint32_t data_secs;
|
||||
char *override;
|
||||
ventoy_virt_chunk *cur;
|
||||
|
||||
override = (char *)chain + chain->virt_chunk_offset;
|
||||
cur = (ventoy_virt_chunk *)override;
|
||||
|
||||
sector = (isosize + 2047) / 2048;
|
||||
offset = 2 * sizeof(ventoy_virt_chunk);
|
||||
|
||||
if (g_conf_new_len > 0)
|
||||
{
|
||||
ventoy_unix_fill_virt(g_conf_new_data, g_conf_new_len);
|
||||
}
|
||||
|
||||
if (g_mod_new_len > 0)
|
||||
{
|
||||
ventoy_unix_fill_virt(g_mod_new_data, g_mod_new_len);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int ventoy_freebsd_append_conf(char *buf, const char *isopath)
|
||||
{
|
||||
int pos = 0;
|
||||
grub_uint32_t i;
|
||||
grub_disk_t disk;
|
||||
grub_file_t isofile;
|
||||
char uuid[64] = {0};
|
||||
ventoy_img_chunk *chunk;
|
||||
grub_uint8_t disk_sig[4];
|
||||
grub_uint8_t disk_guid[16];
|
||||
|
||||
debug("ventoy_freebsd_append_conf %s\n", isopath);
|
||||
|
||||
isofile = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", isopath);
|
||||
if (!isofile)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
vtoy_ssprintf(buf, pos, "ventoy_load=\"%s\"\n", "YES");
|
||||
vtoy_ssprintf(buf, pos, "ventoy_name=\"%s\"\n", g_ko_mod_path);
|
||||
|
||||
disk = isofile->device->disk;
|
||||
|
||||
ventoy_get_disk_guid(isofile->name, disk_guid, disk_sig);
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
grub_snprintf(uuid + i * 2, sizeof(uuid), "%02x", disk_guid[i]);
|
||||
}
|
||||
|
||||
vtoy_ssprintf(buf, pos, "hint.ventoy.0.disksize=%llu\n", (ulonglong)(disk->total_sectors * (1 << disk->log_sector_size)));
|
||||
vtoy_ssprintf(buf, pos, "hint.ventoy.0.diskuuid=\"%s\"\n", uuid);
|
||||
vtoy_ssprintf(buf, pos, "hint.ventoy.0.disksignature=%02x%02x%02x%02x\n", disk_sig[0], disk_sig[1], disk_sig[2], disk_sig[3]);
|
||||
vtoy_ssprintf(buf, pos, "hint.ventoy.0.segnum=%u\n", g_img_chunk_list.cur_chunk);
|
||||
|
||||
for (i = 0; i < g_img_chunk_list.cur_chunk; i++)
|
||||
{
|
||||
chunk = g_img_chunk_list.chunk + i;
|
||||
vtoy_ssprintf(buf, pos, "hint.ventoy.%u.seg=\"0x%llx@0x%llx\"\n",
|
||||
i, (ulonglong)(chunk->disk_start_sector * 512),
|
||||
(ulonglong)((chunk->disk_end_sector + 1) * 512));
|
||||
}
|
||||
|
||||
grub_file_close(isofile);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_unix_reset(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
(void)ctxt;
|
||||
(void)argc;
|
||||
(void)args;
|
||||
|
||||
g_conf_new_len = 0;
|
||||
g_mod_new_len = 0;
|
||||
g_mod_override_offset = 0;
|
||||
g_conf_override_offset = 0;
|
||||
|
||||
check_free(g_mod_new_data, grub_free);
|
||||
check_free(g_conf_new_data, grub_free);
|
||||
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_parse_freenas_ver(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
grub_file_t file;
|
||||
const char *ver = NULL;
|
||||
char *buf = NULL;
|
||||
VTOY_JSON *json = NULL;
|
||||
|
||||
(void)ctxt;
|
||||
(void)argc;
|
||||
|
||||
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
|
||||
if (!file)
|
||||
{
|
||||
debug("Failed to open file %s\n", args[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
buf = grub_malloc(file->size + 2);
|
||||
if (!buf)
|
||||
{
|
||||
grub_file_close(file);
|
||||
return 0;
|
||||
}
|
||||
grub_file_read(file, buf, file->size);
|
||||
buf[file->size] = 0;
|
||||
|
||||
json = vtoy_json_create();
|
||||
if (!json)
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (vtoy_json_parse(json, buf))
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
|
||||
ver = vtoy_json_get_string_ex(json->pstChild, "Version");
|
||||
if (ver)
|
||||
{
|
||||
debug("freenas version:<%s>\n", ver);
|
||||
ventoy_set_env(args[1], ver);
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("freenas version:<%s>\n", "NOT FOUND");
|
||||
grub_env_unset(args[1]);
|
||||
}
|
||||
|
||||
end:
|
||||
grub_check_free(buf);
|
||||
check_free(json, vtoy_json_destroy);
|
||||
grub_file_close(file);
|
||||
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_unix_freebsd_ver(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
grub_file_t file;
|
||||
char *buf;
|
||||
char *start = NULL;
|
||||
char *nextline = NULL;
|
||||
|
||||
(void)ctxt;
|
||||
(void)argc;
|
||||
(void)args;
|
||||
|
||||
file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s", args[0]);
|
||||
if (!file)
|
||||
{
|
||||
debug("Failed to open file %s\n", args[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
buf = grub_zalloc(file->size + 2);
|
||||
if (!buf)
|
||||
{
|
||||
grub_file_close(file);
|
||||
return 0;
|
||||
}
|
||||
grub_file_read(file, buf, file->size);
|
||||
|
||||
for (start = buf; start; start = nextline)
|
||||
{
|
||||
if (grub_strncmp(start, "USERLAND_VERSION", 16) == 0)
|
||||
{
|
||||
nextline = start;
|
||||
while (*nextline && *nextline != '\r' && *nextline != '\n')
|
||||
{
|
||||
nextline++;
|
||||
}
|
||||
|
||||
*nextline = 0;
|
||||
break;
|
||||
}
|
||||
nextline = ventoy_get_line(start);
|
||||
}
|
||||
|
||||
if (start)
|
||||
{
|
||||
debug("freebsd version:<%s>\n", start);
|
||||
ventoy_set_env(args[1], start);
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("freebsd version:<%s>\n", "NOT FOUND");
|
||||
grub_env_unset(args[1]);
|
||||
}
|
||||
|
||||
grub_free(buf);
|
||||
grub_file_close(file);
|
||||
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_unix_replace_conf(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
grub_uint32_t i;
|
||||
char *data;
|
||||
grub_uint64_t offset;
|
||||
grub_file_t file;
|
||||
const char *confile = NULL;
|
||||
const char * loader_conf[] =
|
||||
{
|
||||
"/boot/loader.conf",
|
||||
"/boot/defaults/loader.conf",
|
||||
};
|
||||
|
||||
(void)ctxt;
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
debug("Replace conf invalid argc %d\n", argc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(loader_conf) / sizeof(loader_conf[0]); i++)
|
||||
{
|
||||
if (ventoy_get_file_override(loader_conf[i], &offset) == 0)
|
||||
{
|
||||
confile = loader_conf[i];
|
||||
g_conf_override_offset = offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (confile == NULL)
|
||||
{
|
||||
debug("Can't find loader.conf file from %u locations\n", i);
|
||||
return 1;
|
||||
}
|
||||
|
||||
file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "(loop)/%s", confile);
|
||||
if (!file)
|
||||
{
|
||||
debug("Failed to open %s \n", confile);
|
||||
return 1;
|
||||
}
|
||||
|
||||
debug("old conf file size:%d\n", (int)file->size);
|
||||
|
||||
data = grub_malloc(VTOY_MAX_SCRIPT_BUF);
|
||||
if (!data)
|
||||
{
|
||||
grub_file_close(file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
grub_file_read(file, data, file->size);
|
||||
grub_file_close(file);
|
||||
|
||||
g_conf_new_data = data;
|
||||
g_conf_new_len = (int)file->size;
|
||||
|
||||
if (grub_strcmp(args[0], "FreeBSD") == 0)
|
||||
{
|
||||
g_conf_new_len += ventoy_freebsd_append_conf(data + file->size, args[1]);
|
||||
}
|
||||
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_unix_replace_ko(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
char *data;
|
||||
grub_uint64_t offset;
|
||||
grub_file_t file;
|
||||
|
||||
(void)ctxt;
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
debug("Replace ko invalid argc %d\n", argc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
debug("replace ko %s\n", args[0]);
|
||||
|
||||
if (ventoy_get_file_override(args[0], &offset) == 0)
|
||||
{
|
||||
grub_snprintf(g_ko_mod_path, sizeof(g_ko_mod_path), "%s", args[0]);
|
||||
g_mod_override_offset = offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("Can't find replace ko file from %s\n", args[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s", args[1]);
|
||||
if (!file)
|
||||
{
|
||||
debug("Failed to open %s \n", args[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
debug("new ko file size:%d\n", (int)file->size);
|
||||
|
||||
data = grub_malloc(file->size);
|
||||
if (!data)
|
||||
{
|
||||
grub_file_close(file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
grub_file_read(file, data, file->size);
|
||||
grub_file_close(file);
|
||||
|
||||
g_mod_new_data = data;
|
||||
g_mod_new_len = (int)file->size;
|
||||
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_unix_chain_data(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
int ventoy_compatible = 0;
|
||||
grub_uint32_t size = 0;
|
||||
grub_uint64_t isosize = 0;
|
||||
grub_uint32_t boot_catlog = 0;
|
||||
grub_uint32_t img_chunk_size = 0;
|
||||
grub_uint32_t override_count = 0;
|
||||
grub_uint32_t override_size = 0;
|
||||
grub_uint32_t virt_chunk_size = 0;
|
||||
grub_file_t file;
|
||||
grub_disk_t disk;
|
||||
const char *pLastChain = NULL;
|
||||
const char *compatible;
|
||||
ventoy_chain_head *chain;
|
||||
char envbuf[64];
|
||||
|
||||
(void)ctxt;
|
||||
(void)argc;
|
||||
|
||||
compatible = grub_env_get("ventoy_compatible");
|
||||
if (compatible && compatible[0] == 'Y')
|
||||
{
|
||||
ventoy_compatible = 1;
|
||||
}
|
||||
|
||||
if (NULL == g_img_chunk_list.chunk)
|
||||
{
|
||||
grub_printf("ventoy not ready\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
|
||||
if (!file)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
isosize = file->size;
|
||||
|
||||
boot_catlog = ventoy_get_iso_boot_catlog(file);
|
||||
if (boot_catlog)
|
||||
{
|
||||
if (ventoy_is_efi_os() && (!ventoy_has_efi_eltorito(file, boot_catlog)))
|
||||
{
|
||||
grub_env_set("LoadIsoEfiDriver", "on");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ventoy_is_efi_os())
|
||||
{
|
||||
grub_env_set("LoadIsoEfiDriver", "on");
|
||||
}
|
||||
else
|
||||
{
|
||||
return grub_error(GRUB_ERR_BAD_ARGUMENT, "File %s is not bootable", args[0]);
|
||||
}
|
||||
}
|
||||
|
||||
img_chunk_size = g_img_chunk_list.cur_chunk * sizeof(ventoy_img_chunk);
|
||||
|
||||
if (ventoy_compatible)
|
||||
{
|
||||
size = sizeof(ventoy_chain_head) + img_chunk_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
override_count = ventoy_unix_get_override_chunk_count();
|
||||
override_size = override_count * sizeof(ventoy_override_chunk);
|
||||
|
||||
virt_chunk_size = ventoy_unix_get_virt_chunk_size();
|
||||
size = sizeof(ventoy_chain_head) + img_chunk_size + override_size + virt_chunk_size;
|
||||
}
|
||||
|
||||
pLastChain = grub_env_get("vtoy_chain_mem_addr");
|
||||
if (pLastChain)
|
||||
{
|
||||
chain = (ventoy_chain_head *)grub_strtoul(pLastChain, NULL, 16);
|
||||
if (chain)
|
||||
{
|
||||
debug("free last chain memory %p\n", chain);
|
||||
grub_free(chain);
|
||||
}
|
||||
}
|
||||
|
||||
chain = grub_malloc(size);
|
||||
if (!chain)
|
||||
{
|
||||
grub_printf("Failed to alloc chain memory size %u\n", size);
|
||||
grub_file_close(file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
grub_snprintf(envbuf, sizeof(envbuf), "0x%lx", (unsigned long)chain);
|
||||
grub_env_set("vtoy_chain_mem_addr", envbuf);
|
||||
grub_snprintf(envbuf, sizeof(envbuf), "%u", size);
|
||||
grub_env_set("vtoy_chain_mem_size", envbuf);
|
||||
|
||||
grub_memset(chain, 0, sizeof(ventoy_chain_head));
|
||||
|
||||
/* part 1: os parameter */
|
||||
g_ventoy_chain_type = ventoy_chain_linux;
|
||||
ventoy_fill_os_param(file, &(chain->os_param));
|
||||
|
||||
/* part 2: chain head */
|
||||
disk = file->device->disk;
|
||||
chain->disk_drive = disk->id;
|
||||
chain->disk_sector_size = (1 << disk->log_sector_size);
|
||||
chain->real_img_size_in_bytes = file->size;
|
||||
chain->virt_img_size_in_bytes = (file->size + 2047) / 2048 * 2048;
|
||||
chain->boot_catalog = boot_catlog;
|
||||
|
||||
if (!ventoy_is_efi_os())
|
||||
{
|
||||
grub_file_seek(file, boot_catlog * 2048);
|
||||
grub_file_read(file, chain->boot_catalog_sector, sizeof(chain->boot_catalog_sector));
|
||||
}
|
||||
|
||||
/* part 3: image chunk */
|
||||
chain->img_chunk_offset = sizeof(ventoy_chain_head);
|
||||
chain->img_chunk_num = g_img_chunk_list.cur_chunk;
|
||||
grub_memcpy((char *)chain + chain->img_chunk_offset, g_img_chunk_list.chunk, img_chunk_size);
|
||||
|
||||
if (ventoy_compatible)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* part 4: override chunk */
|
||||
chain->override_chunk_offset = chain->img_chunk_offset + img_chunk_size;
|
||||
chain->override_chunk_num = override_count;
|
||||
ventoy_unix_fill_override_data(isosize, (char *)chain + chain->override_chunk_offset);
|
||||
|
||||
/* part 5: virt chunk */
|
||||
chain->virt_chunk_offset = chain->override_chunk_offset + override_size;
|
||||
chain->virt_chunk_num = ventoy_unix_get_virt_chunk_count();
|
||||
ventoy_unix_fill_virt_data(isosize, chain);
|
||||
|
||||
grub_file_close(file);
|
||||
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
559
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_vhd.c
Normal file
@@ -0,0 +1,559 @@
|
||||
/******************************************************************************
|
||||
* ventoy_vhd.c
|
||||
*
|
||||
* Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <grub/types.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/device.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/partition.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/datetime.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/net.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/crypto.h>
|
||||
#include <grub/charset.h>
|
||||
#ifdef GRUB_MACHINE_EFI
|
||||
#include <grub/efi/efi.h>
|
||||
#endif
|
||||
#include <grub/ventoy.h>
|
||||
#include "ventoy_def.h"
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static int g_vhdboot_bcd_offset = 0;
|
||||
static int g_vhdboot_bcd_len = 0;
|
||||
static int g_vhdboot_isolen = 0;
|
||||
static char *g_vhdboot_totbuf = NULL;
|
||||
static char *g_vhdboot_isobuf = NULL;
|
||||
static grub_uint64_t g_img_trim_head_secnum = 0;
|
||||
|
||||
static int ventoy_vhd_find_bcd(int *bcdoffset, int *bcdlen)
|
||||
{
|
||||
grub_uint32_t offset;
|
||||
grub_file_t file;
|
||||
char cmdbuf[128];
|
||||
|
||||
grub_snprintf(cmdbuf, sizeof(cmdbuf), "loopback vhdiso mem:0x%lx:size:%d", (ulong)g_vhdboot_isobuf, g_vhdboot_isolen);
|
||||
|
||||
grub_script_execute_sourcecode(cmdbuf);
|
||||
|
||||
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", "(vhdiso)/boot/bcd");
|
||||
if (!file)
|
||||
{
|
||||
grub_printf("Failed to open bcd file in the image file\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
grub_file_read(file, &offset, 4);
|
||||
offset = (grub_uint32_t)grub_iso9660_get_last_read_pos(file);
|
||||
|
||||
*bcdoffset = (int)offset;
|
||||
*bcdlen = (int)file->size;
|
||||
|
||||
debug("vhdiso bcd file offset:%d len:%d\n", *bcdoffset, *bcdlen);
|
||||
|
||||
grub_file_close(file);
|
||||
|
||||
grub_script_execute_sourcecode("loopback -d vhdiso");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ventoy_vhd_patch_path(char *vhdpath, ventoy_patch_vhd *patch1, ventoy_patch_vhd *patch2)
|
||||
{
|
||||
int i;
|
||||
int cnt = 0;
|
||||
char *pos;
|
||||
grub_size_t pathlen;
|
||||
const char *plat;
|
||||
grub_uint16_t *unicode_path;
|
||||
const grub_uint8_t winloadexe[] =
|
||||
{
|
||||
0x77, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x6C, 0x00, 0x6F, 0x00, 0x61, 0x00, 0x64, 0x00, 0x2E, 0x00,
|
||||
0x65, 0x00, 0x78, 0x00, 0x65, 0x00
|
||||
};
|
||||
|
||||
pathlen = sizeof(grub_uint16_t) * (grub_strlen(vhdpath) + 1);
|
||||
debug("unicode path for <%s> len:%d\n", vhdpath, (int)pathlen);
|
||||
|
||||
unicode_path = grub_zalloc(pathlen);
|
||||
if (!unicode_path)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
plat = grub_env_get("grub_platform");
|
||||
|
||||
if (plat && (plat[0] == 'e')) /* UEFI */
|
||||
{
|
||||
pos = g_vhdboot_isobuf + g_vhdboot_bcd_offset;
|
||||
|
||||
/* winload.exe ==> winload.efi */
|
||||
for (i = 0; i + (int)sizeof(winloadexe) < g_vhdboot_bcd_len; i++)
|
||||
{
|
||||
if (*((grub_uint32_t *)(pos + i)) == 0x00690077 &&
|
||||
grub_memcmp(pos + i, winloadexe, sizeof(winloadexe)) == 0)
|
||||
{
|
||||
pos[i + sizeof(winloadexe) - 4] = 0x66;
|
||||
pos[i + sizeof(winloadexe) - 2] = 0x69;
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
debug("winload patch %d times\n", cnt);
|
||||
}
|
||||
|
||||
for (pos = vhdpath; *pos; pos++)
|
||||
{
|
||||
if (*pos == '/')
|
||||
{
|
||||
*pos = '\\';
|
||||
}
|
||||
}
|
||||
|
||||
grub_utf8_to_utf16(unicode_path, pathlen, (grub_uint8_t *)vhdpath, -1, NULL);
|
||||
grub_memcpy(patch1->vhd_file_path, unicode_path, pathlen);
|
||||
grub_memcpy(patch2->vhd_file_path, unicode_path, pathlen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ventoy_vhd_patch_disk(ventoy_patch_vhd *patch1, ventoy_patch_vhd *patch2)
|
||||
{
|
||||
char efipart[16] = {0};
|
||||
|
||||
grub_memcpy(efipart, g_ventoy_part_info->Head.Signature, sizeof(g_ventoy_part_info->Head.Signature));
|
||||
|
||||
debug("part1 type: 0x%x <%s>\n", g_ventoy_part_info->MBR.PartTbl[0].FsFlag, efipart);
|
||||
|
||||
if (grub_strncmp(efipart, "EFI PART", 8) == 0)
|
||||
{
|
||||
ventoy_debug_dump_guid("GPT disk GUID: ", g_ventoy_part_info->Head.DiskGuid);
|
||||
ventoy_debug_dump_guid("GPT part GUID: ", g_ventoy_part_info->PartTbl[0].PartGuid);
|
||||
|
||||
grub_memcpy(patch1->disk_signature_or_guid, g_ventoy_part_info->Head.DiskGuid, 16);
|
||||
grub_memcpy(patch1->part_offset_or_guid, g_ventoy_part_info->PartTbl[0].PartGuid, 16);
|
||||
grub_memcpy(patch2->disk_signature_or_guid, g_ventoy_part_info->Head.DiskGuid, 16);
|
||||
grub_memcpy(patch2->part_offset_or_guid, g_ventoy_part_info->PartTbl[0].PartGuid, 16);
|
||||
|
||||
patch1->part_type = patch2->part_type = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("MBR disk signature: %02x%02x%02x%02x\n",
|
||||
g_ventoy_part_info->MBR.BootCode[0x1b8 + 0], g_ventoy_part_info->MBR.BootCode[0x1b8 + 1],
|
||||
g_ventoy_part_info->MBR.BootCode[0x1b8 + 2], g_ventoy_part_info->MBR.BootCode[0x1b8 + 3]);
|
||||
grub_memcpy(patch1->disk_signature_or_guid, g_ventoy_part_info->MBR.BootCode + 0x1b8, 4);
|
||||
grub_memcpy(patch2->disk_signature_or_guid, g_ventoy_part_info->MBR.BootCode + 0x1b8, 4);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_patch_vhdboot(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
int rc;
|
||||
ventoy_patch_vhd *patch1;
|
||||
ventoy_patch_vhd *patch2;
|
||||
char envbuf[64];
|
||||
|
||||
(void)ctxt;
|
||||
(void)argc;
|
||||
|
||||
grub_env_unset("vtoy_vhd_buf_addr");
|
||||
|
||||
debug("patch vhd <%s>\n", args[0]);
|
||||
|
||||
if ((!g_vhdboot_enable) || (!g_vhdboot_totbuf))
|
||||
{
|
||||
debug("vhd boot not ready %d %p\n", g_vhdboot_enable, g_vhdboot_totbuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = ventoy_vhd_find_bcd(&g_vhdboot_bcd_offset, &g_vhdboot_bcd_len);
|
||||
if (rc)
|
||||
{
|
||||
debug("failed to get bcd location %d\n", rc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
patch1 = (ventoy_patch_vhd *)(g_vhdboot_isobuf + g_vhdboot_bcd_offset + 0x495a);
|
||||
patch2 = (ventoy_patch_vhd *)(g_vhdboot_isobuf + g_vhdboot_bcd_offset + 0x50aa);
|
||||
|
||||
ventoy_vhd_patch_disk(patch1, patch2);
|
||||
ventoy_vhd_patch_path(args[0], patch1, patch2);
|
||||
|
||||
/* set buffer and size */
|
||||
#ifdef GRUB_MACHINE_EFI
|
||||
grub_snprintf(envbuf, sizeof(envbuf), "0x%lx", (ulong)g_vhdboot_totbuf);
|
||||
grub_env_set("vtoy_vhd_buf_addr", envbuf);
|
||||
grub_snprintf(envbuf, sizeof(envbuf), "%d", (int)(g_vhdboot_isolen + sizeof(ventoy_chain_head)));
|
||||
grub_env_set("vtoy_vhd_buf_size", envbuf);
|
||||
#else
|
||||
grub_snprintf(envbuf, sizeof(envbuf), "0x%lx", (ulong)g_vhdboot_isobuf);
|
||||
grub_env_set("vtoy_vhd_buf_addr", envbuf);
|
||||
grub_snprintf(envbuf, sizeof(envbuf), "%d", g_vhdboot_isolen);
|
||||
grub_env_set("vtoy_vhd_buf_size", envbuf);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_load_vhdboot(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
int buflen;
|
||||
grub_file_t file;
|
||||
|
||||
(void)ctxt;
|
||||
(void)argc;
|
||||
|
||||
g_vhdboot_enable = 0;
|
||||
grub_check_free(g_vhdboot_totbuf);
|
||||
|
||||
file = grub_file_open(args[0], VENTOY_FILE_TYPE);
|
||||
if (!file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
debug("load vhd boot: <%s> <%lu>\n", args[0], (ulong)file->size);
|
||||
|
||||
if (file->size < VTOY_SIZE_1KB * 32)
|
||||
{
|
||||
grub_file_close(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
g_vhdboot_isolen = (int)file->size;
|
||||
|
||||
buflen = (int)(file->size + sizeof(ventoy_chain_head));
|
||||
|
||||
#ifdef GRUB_MACHINE_EFI
|
||||
g_vhdboot_totbuf = (char *)grub_efi_allocate_iso_buf(buflen);
|
||||
#else
|
||||
g_vhdboot_totbuf = (char *)grub_malloc(buflen);
|
||||
#endif
|
||||
|
||||
if (!g_vhdboot_totbuf)
|
||||
{
|
||||
grub_file_close(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
g_vhdboot_isobuf = g_vhdboot_totbuf + sizeof(ventoy_chain_head);
|
||||
|
||||
grub_file_read(file, g_vhdboot_isobuf, file->size);
|
||||
grub_file_close(file);
|
||||
|
||||
g_vhdboot_enable = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ventoy_raw_trim_head(grub_uint64_t offset)
|
||||
{
|
||||
grub_uint32_t i;
|
||||
grub_uint32_t memsize;
|
||||
grub_uint32_t imgstart = 0;
|
||||
grub_uint32_t imgsecs = 0;
|
||||
grub_uint64_t sectors = 0;
|
||||
grub_uint64_t cursecs = 0;
|
||||
grub_uint64_t delta = 0;
|
||||
|
||||
if ((!g_img_chunk_list.chunk) || (!offset))
|
||||
{
|
||||
debug("image chunk not ready %p %lu\n", g_img_chunk_list.chunk, (ulong)offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
debug("image trim head %lu\n", (ulong)offset);
|
||||
|
||||
for (i = 0; i < g_img_chunk_list.cur_chunk; i++)
|
||||
{
|
||||
cursecs = g_img_chunk_list.chunk[i].disk_end_sector + 1 - g_img_chunk_list.chunk[i].disk_start_sector;
|
||||
sectors += cursecs;
|
||||
if (sectors >= offset)
|
||||
{
|
||||
delta = cursecs - (sectors - offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sectors < offset || i >= g_img_chunk_list.cur_chunk)
|
||||
{
|
||||
debug("Invalid size %lu %lu\n", (ulong)sectors, (ulong)offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sectors == offset)
|
||||
{
|
||||
memsize = (g_img_chunk_list.cur_chunk - (i + 1)) * sizeof(ventoy_img_chunk);
|
||||
grub_memmove(g_img_chunk_list.chunk, g_img_chunk_list.chunk + i + 1, memsize);
|
||||
g_img_chunk_list.cur_chunk -= (i + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_img_chunk_list.chunk[i].disk_start_sector += delta;
|
||||
g_img_chunk_list.chunk[i].img_start_sector += (grub_uint32_t)(delta / 4);
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
memsize = (g_img_chunk_list.cur_chunk - i) * sizeof(ventoy_img_chunk);
|
||||
grub_memmove(g_img_chunk_list.chunk, g_img_chunk_list.chunk + i, memsize);
|
||||
g_img_chunk_list.cur_chunk -= i;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < g_img_chunk_list.cur_chunk; i++)
|
||||
{
|
||||
imgsecs = g_img_chunk_list.chunk[i].img_end_sector + 1 - g_img_chunk_list.chunk[i].img_start_sector;
|
||||
g_img_chunk_list.chunk[i].img_start_sector = imgstart;
|
||||
g_img_chunk_list.chunk[i].img_end_sector = imgstart + (imgsecs - 1);
|
||||
imgstart += imgsecs;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_get_vtoy_type(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
int i;
|
||||
int offset = -1;
|
||||
grub_file_t file;
|
||||
vhd_footer_t vhdfoot;
|
||||
VDIPREHEADER vdihdr;
|
||||
char type[16] = {0};
|
||||
ventoy_gpt_info *gpt;
|
||||
|
||||
(void)ctxt;
|
||||
|
||||
g_img_trim_head_secnum = 0;
|
||||
|
||||
if (argc != 4)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
file = grub_file_open(args[0], VENTOY_FILE_TYPE);
|
||||
if (!file)
|
||||
{
|
||||
debug("Failed to open file %s\n", args[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_snprintf(type, sizeof(type), "unknown");
|
||||
|
||||
grub_file_seek(file, file->size - 512);
|
||||
grub_file_read(file, &vhdfoot, sizeof(vhdfoot));
|
||||
|
||||
if (grub_strncmp(vhdfoot.cookie, "conectix", 8) == 0)
|
||||
{
|
||||
offset = 0;
|
||||
grub_snprintf(type, sizeof(type), "vhd%u", grub_swap_bytes32(vhdfoot.disktype));
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_file_seek(file, 0);
|
||||
grub_file_read(file, &vdihdr, sizeof(vdihdr));
|
||||
if (vdihdr.u32Signature == VDI_IMAGE_SIGNATURE &&
|
||||
grub_strncmp(vdihdr.szFileInfo, VDI_IMAGE_FILE_INFO, grub_strlen(VDI_IMAGE_FILE_INFO)) == 0)
|
||||
{
|
||||
offset = 2 * 1048576;
|
||||
g_img_trim_head_secnum = offset / 512;
|
||||
grub_snprintf(type, sizeof(type), "vdi");
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = 0;
|
||||
grub_snprintf(type, sizeof(type), "raw");
|
||||
}
|
||||
}
|
||||
|
||||
grub_env_set(args[1], type);
|
||||
debug("<%s> vtoy type: <%s> ", args[0], type);
|
||||
|
||||
if (offset >= 0)
|
||||
{
|
||||
gpt = grub_zalloc(sizeof(ventoy_gpt_info));
|
||||
if (!gpt)
|
||||
{
|
||||
grub_env_set(args[1], "unknown");
|
||||
goto end;
|
||||
}
|
||||
|
||||
grub_file_seek(file, offset);
|
||||
grub_file_read(file, gpt, sizeof(ventoy_gpt_info));
|
||||
|
||||
if (gpt->MBR.Byte55 != 0x55 || gpt->MBR.ByteAA != 0xAA)
|
||||
{
|
||||
grub_env_set(args[1], "unknown");
|
||||
debug("invalid mbr signature: 0x%x 0x%x\n", gpt->MBR.Byte55, gpt->MBR.ByteAA);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (grub_memcmp(gpt->Head.Signature, "EFI PART", 8) == 0)
|
||||
{
|
||||
grub_env_set(args[2], "gpt");
|
||||
debug("part type: %s\n", "GPT");
|
||||
|
||||
if (gpt->MBR.PartTbl[0].FsFlag == 0xEE)
|
||||
{
|
||||
for (i = 0; i < 128; i++)
|
||||
{
|
||||
if (grub_memcmp(gpt->PartTbl[i].PartType, "Hah!IdontNeedEFI", 16) == 0)
|
||||
{
|
||||
debug("part %d is grub_bios part\n", i);
|
||||
grub_env_set(args[3], "1");
|
||||
break;
|
||||
}
|
||||
else if (gpt->PartTbl[i].LastLBA == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_env_set(args[2], "mbr");
|
||||
debug("part type: %s\n", "MBR");
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
if (gpt->MBR.PartTbl[i].FsFlag == 0xEF)
|
||||
{
|
||||
debug("part %d is esp part in MBR mode\n", i);
|
||||
grub_env_set(args[3], "1");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("part type: %s\n", "xxx");
|
||||
}
|
||||
|
||||
end:
|
||||
grub_check_free(gpt);
|
||||
grub_file_close(file);
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
||||
|
||||
grub_err_t ventoy_cmd_raw_chain_data(grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
grub_uint32_t size = 0;
|
||||
grub_uint32_t img_chunk_size = 0;
|
||||
grub_file_t file;
|
||||
grub_disk_t disk;
|
||||
const char *pLastChain = NULL;
|
||||
ventoy_chain_head *chain;
|
||||
char envbuf[64];
|
||||
|
||||
(void)ctxt;
|
||||
(void)argc;
|
||||
|
||||
if (NULL == g_img_chunk_list.chunk)
|
||||
{
|
||||
grub_printf("ventoy not ready\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (g_img_trim_head_secnum > 0)
|
||||
{
|
||||
ventoy_raw_trim_head(g_img_trim_head_secnum);
|
||||
}
|
||||
|
||||
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
|
||||
if (!file)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
img_chunk_size = g_img_chunk_list.cur_chunk * sizeof(ventoy_img_chunk);
|
||||
|
||||
size = sizeof(ventoy_chain_head) + img_chunk_size;
|
||||
|
||||
pLastChain = grub_env_get("vtoy_chain_mem_addr");
|
||||
if (pLastChain)
|
||||
{
|
||||
chain = (ventoy_chain_head *)grub_strtoul(pLastChain, NULL, 16);
|
||||
if (chain)
|
||||
{
|
||||
debug("free last chain memory %p\n", chain);
|
||||
grub_free(chain);
|
||||
}
|
||||
}
|
||||
|
||||
chain = grub_malloc(size);
|
||||
if (!chain)
|
||||
{
|
||||
grub_printf("Failed to alloc chain memory size %u\n", size);
|
||||
grub_file_close(file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
grub_snprintf(envbuf, sizeof(envbuf), "0x%lx", (unsigned long)chain);
|
||||
grub_env_set("vtoy_chain_mem_addr", envbuf);
|
||||
grub_snprintf(envbuf, sizeof(envbuf), "%u", size);
|
||||
grub_env_set("vtoy_chain_mem_size", envbuf);
|
||||
|
||||
grub_env_export("vtoy_chain_mem_addr");
|
||||
grub_env_export("vtoy_chain_mem_size");
|
||||
|
||||
grub_memset(chain, 0, sizeof(ventoy_chain_head));
|
||||
|
||||
/* part 1: os parameter */
|
||||
g_ventoy_chain_type = ventoy_chain_linux;
|
||||
ventoy_fill_os_param(file, &(chain->os_param));
|
||||
|
||||
/* part 2: chain head */
|
||||
disk = file->device->disk;
|
||||
chain->disk_drive = disk->id;
|
||||
chain->disk_sector_size = (1 << disk->log_sector_size);
|
||||
|
||||
chain->real_img_size_in_bytes = file->size;
|
||||
if (g_img_trim_head_secnum > 0)
|
||||
{
|
||||
chain->real_img_size_in_bytes -= g_img_trim_head_secnum * 512;
|
||||
}
|
||||
|
||||
chain->virt_img_size_in_bytes = chain->real_img_size_in_bytes;
|
||||
chain->boot_catalog = 0;
|
||||
|
||||
/* part 3: image chunk */
|
||||
chain->img_chunk_offset = sizeof(ventoy_chain_head);
|
||||
chain->img_chunk_num = g_img_chunk_list.cur_chunk;
|
||||
grub_memcpy((char *)chain + chain->img_chunk_offset, g_img_chunk_list.chunk, img_chunk_size);
|
||||
|
||||
grub_file_seek(file, g_img_trim_head_secnum * 512);
|
||||
grub_file_read(file, chain->boot_catalog_sector, 512);
|
||||
|
||||
grub_file_close(file);
|
||||
|
||||
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
|
||||
}
|
53
GRUB2/MOD_SRC/grub-2.04/include/grub/compiler.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/* compiler.h - macros for various compiler features */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2002,2003,2005,2006,2007,2008,2009,2010,2014 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GRUB_COMPILER_HEADER
|
||||
#define GRUB_COMPILER_HEADER 1
|
||||
|
||||
/* GCC version checking borrowed from glibc. */
|
||||
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
|
||||
# define GNUC_PREREQ(maj,min) \
|
||||
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
|
||||
#else
|
||||
# define GNUC_PREREQ(maj,min) 0
|
||||
#endif
|
||||
|
||||
/* Does this compiler support compile-time error attributes? */
|
||||
#if GNUC_PREREQ(4,3)
|
||||
# define ATTRIBUTE_ERROR(msg) \
|
||||
__attribute__ ((__error__ (msg)))
|
||||
#else
|
||||
# define ATTRIBUTE_ERROR(msg) __attribute__ ((noreturn))
|
||||
#endif
|
||||
|
||||
#if GNUC_PREREQ(4,4)
|
||||
# define GNU_PRINTF gnu_printf
|
||||
#else
|
||||
# define GNU_PRINTF printf
|
||||
#endif
|
||||
|
||||
#if GNUC_PREREQ(3,4)
|
||||
# define WARN_UNUSED_RESULT __attribute__ ((warn_unused_result))
|
||||
#else
|
||||
# define WARN_UNUSED_RESULT
|
||||
#endif
|
||||
|
||||
#define UNUSED __attribute__((__unused__))
|
||||
|
||||
#endif /* ! GRUB_COMPILER_HEADER */
|
133
GRUB2/MOD_SRC/grub-2.04/include/grub/kernel.h
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2002,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GRUB_KERNEL_HEADER
|
||||
#define GRUB_KERNEL_HEADER 1
|
||||
|
||||
#include <grub/types.h>
|
||||
#include <grub/symbol.h>
|
||||
|
||||
enum
|
||||
{
|
||||
OBJ_TYPE_ELF,
|
||||
OBJ_TYPE_MEMDISK,
|
||||
OBJ_TYPE_CONFIG,
|
||||
OBJ_TYPE_PREFIX,
|
||||
OBJ_TYPE_PUBKEY,
|
||||
OBJ_TYPE_DTB
|
||||
};
|
||||
|
||||
/* The module header. */
|
||||
struct grub_module_header
|
||||
{
|
||||
/* The type of object. */
|
||||
grub_uint32_t type;
|
||||
/* The size of object (including this header). */
|
||||
grub_uint32_t size;
|
||||
};
|
||||
|
||||
/* "gmim" (GRUB Module Info Magic). */
|
||||
#define GRUB_MODULE_MAGIC 0x676d696d
|
||||
|
||||
struct grub_module_info32
|
||||
{
|
||||
/* Magic number so we know we have modules present. */
|
||||
grub_uint32_t magic;
|
||||
/* The offset of the modules. */
|
||||
grub_uint32_t offset;
|
||||
/* The size of all modules plus this header. */
|
||||
grub_uint32_t size;
|
||||
};
|
||||
|
||||
struct grub_module_info64
|
||||
{
|
||||
/* Magic number so we know we have modules present. */
|
||||
grub_uint32_t magic;
|
||||
grub_uint32_t padding;
|
||||
/* The offset of the modules. */
|
||||
grub_uint64_t offset;
|
||||
/* The size of all modules plus this header. */
|
||||
grub_uint64_t size;
|
||||
};
|
||||
|
||||
#ifndef GRUB_UTIL
|
||||
/* Space isn't reusable on some platforms. */
|
||||
/* On Qemu the preload space is readonly. */
|
||||
/* On emu there is no preload space. */
|
||||
/* On ieee1275 our code assumes that heap is p=v which isn't guaranteed for module space. */
|
||||
#if defined (GRUB_MACHINE_QEMU) || defined (GRUB_MACHINE_EMU) \
|
||||
|| defined (GRUB_MACHINE_EFI) \
|
||||
|| (defined (GRUB_MACHINE_IEEE1275) && !defined (__sparc__))
|
||||
#define GRUB_KERNEL_PRELOAD_SPACE_REUSABLE 0
|
||||
#endif
|
||||
|
||||
#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) \
|
||||
|| defined (GRUB_MACHINE_MULTIBOOT) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS) \
|
||||
|| defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_ARC) \
|
||||
|| (defined (__sparc__) && defined (GRUB_MACHINE_IEEE1275)) \
|
||||
|| defined (GRUB_MACHINE_UBOOT) || defined (GRUB_MACHINE_XEN) \
|
||||
|| defined(GRUB_MACHINE_XEN_PVH)
|
||||
/* FIXME: stack is between 2 heap regions. Move it. */
|
||||
#define GRUB_KERNEL_PRELOAD_SPACE_REUSABLE 1
|
||||
#endif
|
||||
|
||||
#ifndef GRUB_KERNEL_PRELOAD_SPACE_REUSABLE
|
||||
#error "Please check if preload space is reusable on this platform!"
|
||||
#endif
|
||||
|
||||
#if GRUB_TARGET_SIZEOF_VOID_P == 8
|
||||
#define grub_module_info grub_module_info64
|
||||
#else
|
||||
#define grub_module_info grub_module_info32
|
||||
#endif
|
||||
|
||||
extern grub_addr_t EXPORT_VAR (grub_modbase);
|
||||
|
||||
void EXPORT_FUNC(ventoy_env_hook_root)(int hook);
|
||||
|
||||
#define FOR_MODULES(var) for (\
|
||||
var = (grub_modbase && ((((struct grub_module_info *) grub_modbase)->magic) == GRUB_MODULE_MAGIC)) ? (struct grub_module_header *) \
|
||||
(grub_modbase + (((struct grub_module_info *) grub_modbase)->offset)) : 0;\
|
||||
var && (grub_addr_t) var \
|
||||
< (grub_modbase + (((struct grub_module_info *) grub_modbase)->size)); \
|
||||
var = (struct grub_module_header *) \
|
||||
(((grub_uint32_t *) var) + ((((struct grub_module_header *) var)->size + sizeof (grub_addr_t) - 1) / sizeof (grub_addr_t)) * (sizeof (grub_addr_t) / sizeof (grub_uint32_t))))
|
||||
|
||||
grub_addr_t grub_modules_get_end (void);
|
||||
|
||||
#endif
|
||||
|
||||
/* The start point of the C code. */
|
||||
void grub_main (void) __attribute__ ((noreturn));
|
||||
|
||||
/* The machine-specific initialization. This must initialize memory. */
|
||||
void grub_machine_init (void);
|
||||
|
||||
/* The machine-specific finalization. */
|
||||
void EXPORT_FUNC(grub_machine_fini) (int flags);
|
||||
|
||||
/* The machine-specific prefix initialization. */
|
||||
void
|
||||
grub_machine_get_bootlocation (char **device, char **path);
|
||||
|
||||
/* Register all the exported symbols. This is automatically generated. */
|
||||
void grub_register_exported_symbols (void);
|
||||
|
||||
extern void (*EXPORT_VAR(grub_net_poll_cards_idle)) (void);
|
||||
|
||||
#endif /* ! GRUB_KERNEL_HEADER */
|
119
GRUB2/MOD_SRC/grub-2.04/include/grub/menu.h
Normal file
@@ -0,0 +1,119 @@
|
||||
/* menu.h - Menu model function prototypes and data structures. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GRUB_MENU_HEADER
|
||||
#define GRUB_MENU_HEADER 1
|
||||
|
||||
struct bls_entry
|
||||
{
|
||||
struct bls_entry *next;
|
||||
struct bls_entry *prev;
|
||||
struct keyval **keyvals;
|
||||
int nkeyvals;
|
||||
char *filename;
|
||||
int visible;
|
||||
};
|
||||
|
||||
struct grub_menu_entry_class
|
||||
{
|
||||
char *name;
|
||||
struct grub_menu_entry_class *next;
|
||||
};
|
||||
|
||||
/* The menu entry. */
|
||||
struct grub_menu_entry
|
||||
{
|
||||
/* The title name. */
|
||||
const char *title;
|
||||
|
||||
/* The identifier. */
|
||||
const char *id;
|
||||
|
||||
/* If set means not everybody is allowed to boot this entry. */
|
||||
int restricted;
|
||||
|
||||
/* Allowed users. */
|
||||
const char *users;
|
||||
|
||||
/* The classes associated with the menu entry:
|
||||
used to choose an icon or other style attributes.
|
||||
This is a dummy head node for the linked list, so for an entry E,
|
||||
E.classes->next is the first class if it is not NULL. */
|
||||
struct grub_menu_entry_class *classes;
|
||||
|
||||
/* The sourcecode of the menu entry, used by the editor. */
|
||||
const char *sourcecode;
|
||||
|
||||
/* Parameters to be passed to menu definition. */
|
||||
int argc;
|
||||
char **args;
|
||||
|
||||
int hotkey;
|
||||
|
||||
int submenu;
|
||||
|
||||
/* The next element. */
|
||||
struct grub_menu_entry *next;
|
||||
|
||||
/* BLS used to populate the entry */
|
||||
struct bls_entry *bls;
|
||||
};
|
||||
typedef struct grub_menu_entry *grub_menu_entry_t;
|
||||
|
||||
/* The menu. */
|
||||
struct grub_menu
|
||||
{
|
||||
/* The size of a menu. */
|
||||
int size;
|
||||
|
||||
/* The list of menu entries. */
|
||||
grub_menu_entry_t entry_list;
|
||||
};
|
||||
typedef struct grub_menu *grub_menu_t;
|
||||
|
||||
/* Callback structure menu viewers can use to provide user feedback when
|
||||
default entries are executed, possibly including fallback entries. */
|
||||
typedef struct grub_menu_execute_callback
|
||||
{
|
||||
/* Called immediately before ENTRY is booted. */
|
||||
void (*notify_booting) (grub_menu_entry_t entry, void *userdata);
|
||||
|
||||
/* Called when executing one entry has failed, and another entry, ENTRY, will
|
||||
be executed as a fallback. The implementation of this function should
|
||||
delay for a period of at least 2 seconds before returning in order to
|
||||
allow the user time to read the information before it can be lost by
|
||||
executing ENTRY. */
|
||||
void (*notify_fallback) (grub_menu_entry_t entry, void *userdata);
|
||||
|
||||
/* Called when an entry has failed to execute and there is no remaining
|
||||
fallback entry to attempt. */
|
||||
void (*notify_failure) (void *userdata);
|
||||
}
|
||||
*grub_menu_execute_callback_t;
|
||||
|
||||
grub_menu_entry_t grub_menu_get_entry (grub_menu_t menu, int no);
|
||||
int grub_menu_get_timeout (void);
|
||||
void grub_menu_set_timeout (int timeout);
|
||||
void grub_menu_entry_run (grub_menu_entry_t entry);
|
||||
int grub_menu_get_default_entry_index (grub_menu_t menu);
|
||||
|
||||
void grub_menu_init (void);
|
||||
void grub_menu_fini (void);
|
||||
|
||||
#endif /* GRUB_MENU_HEADER */
|
177
GRUB2/MOD_SRC/grub-2.04/include/grub/normal.h
Normal file
@@ -0,0 +1,177 @@
|
||||
/* normal.h - prototypes for the normal mode */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2002,2003,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GRUB_NORMAL_HEADER
|
||||
#define GRUB_NORMAL_HEADER 1
|
||||
|
||||
#include <grub/term.h>
|
||||
#include <grub/symbol.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/menu.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/file.h>
|
||||
|
||||
/* The standard left and right margin for some messages. */
|
||||
#define STANDARD_MARGIN 6
|
||||
|
||||
/* The type of a completion item. */
|
||||
enum grub_completion_type
|
||||
{
|
||||
GRUB_COMPLETION_TYPE_COMMAND,
|
||||
GRUB_COMPLETION_TYPE_DEVICE,
|
||||
GRUB_COMPLETION_TYPE_PARTITION,
|
||||
GRUB_COMPLETION_TYPE_FILE,
|
||||
GRUB_COMPLETION_TYPE_ARGUMENT
|
||||
};
|
||||
typedef enum grub_completion_type grub_completion_type_t;
|
||||
|
||||
extern struct grub_menu_viewer grub_normal_text_menu_viewer;
|
||||
extern int grub_normal_exit_level;
|
||||
|
||||
/* Defined in `main.c'. */
|
||||
void grub_enter_normal_mode (const char *config);
|
||||
void grub_normal_execute (const char *config, int nested, int batch);
|
||||
struct grub_term_screen_geometry
|
||||
{
|
||||
/* The number of entries shown at a time. */
|
||||
int num_entries;
|
||||
int first_entry_y;
|
||||
int first_entry_x;
|
||||
int entry_width;
|
||||
int timeout_y;
|
||||
int timeout_lines;
|
||||
int border;
|
||||
int right_margin;
|
||||
};
|
||||
|
||||
void grub_menu_init_page (int nested, int edit,
|
||||
struct grub_term_screen_geometry *geo,
|
||||
struct grub_term_output *term);
|
||||
void grub_normal_init_page (struct grub_term_output *term, int y);
|
||||
char *grub_file_getline (grub_file_t file);
|
||||
void grub_cmdline_run (int nested, int force_auth);
|
||||
|
||||
/* Defined in `cmdline.c'. */
|
||||
char *grub_cmdline_get (const char *prompt);
|
||||
grub_err_t grub_set_history (int newsize);
|
||||
|
||||
/* Defined in `completion.c'. */
|
||||
char *grub_normal_do_completion (char *buf, int *restore,
|
||||
void (*hook) (const char *item, grub_completion_type_t type, int count));
|
||||
|
||||
/* Defined in `misc.c'. */
|
||||
grub_err_t grub_normal_print_device_info (const char *name);
|
||||
|
||||
/* Defined in `color.c'. */
|
||||
char *grub_env_write_color_normal (struct grub_env_var *var, const char *val);
|
||||
char *grub_env_write_color_highlight (struct grub_env_var *var, const char *val);
|
||||
int grub_parse_color_name_pair (grub_uint8_t *ret, const char *name);
|
||||
|
||||
/* Defined in `menu_text.c'. */
|
||||
void grub_wait_after_message (void);
|
||||
void
|
||||
grub_print_ucs4 (const grub_uint32_t * str,
|
||||
const grub_uint32_t * last_position,
|
||||
int margin_left, int margin_right,
|
||||
struct grub_term_output *term);
|
||||
|
||||
void
|
||||
grub_print_ucs4_menu (const grub_uint32_t * str,
|
||||
const grub_uint32_t * last_position,
|
||||
int margin_left, int margin_right,
|
||||
struct grub_term_output *term,
|
||||
int skip_lines, int max_lines, grub_uint32_t contchar,
|
||||
struct grub_term_pos *pos);
|
||||
int
|
||||
grub_ucs4_count_lines (const grub_uint32_t * str,
|
||||
const grub_uint32_t * last_position,
|
||||
int margin_left, int margin_right,
|
||||
struct grub_term_output *term);
|
||||
grub_size_t grub_getstringwidth (grub_uint32_t * str,
|
||||
const grub_uint32_t * last_position,
|
||||
struct grub_term_output *term);
|
||||
void grub_print_message_indented (const char *msg, int margin_left,
|
||||
int margin_right,
|
||||
struct grub_term_output *term);
|
||||
void
|
||||
grub_menu_text_register_instances (int entry, grub_menu_t menu, int nested);
|
||||
grub_err_t
|
||||
grub_show_menu (grub_menu_t menu, int nested, int autobooted);
|
||||
|
||||
/* Defined in `handler.c'. */
|
||||
void read_handler_list (void);
|
||||
void free_handler_list (void);
|
||||
|
||||
/* Defined in `dyncmd.c'. */
|
||||
void read_command_list (const char *prefix);
|
||||
|
||||
/* Defined in `autofs.c'. */
|
||||
void read_fs_list (const char *prefix);
|
||||
|
||||
void grub_context_init (void);
|
||||
void grub_context_fini (void);
|
||||
|
||||
void read_crypto_list (const char *prefix);
|
||||
|
||||
void read_terminal_list (const char *prefix);
|
||||
|
||||
void grub_set_more (int onoff);
|
||||
|
||||
void grub_normal_reset_more (void);
|
||||
|
||||
void grub_xputs_normal (const char *str);
|
||||
|
||||
extern int grub_extractor_level;
|
||||
|
||||
grub_err_t
|
||||
grub_normal_add_menu_entry (int argc, const char **args, char **classes,
|
||||
const char *id,
|
||||
const char *users, const char *hotkey,
|
||||
const char *prefix, const char *sourcecode,
|
||||
int submenu, int *index, struct bls_entry *bls);
|
||||
|
||||
grub_err_t
|
||||
grub_normal_set_password (const char *user, const char *password);
|
||||
|
||||
void grub_normal_free_menu (grub_menu_t menu);
|
||||
|
||||
void grub_normal_auth_init (void);
|
||||
void grub_normal_auth_fini (void);
|
||||
|
||||
void
|
||||
grub_xnputs (const char *str, grub_size_t msg_len);
|
||||
|
||||
grub_command_t
|
||||
grub_dyncmd_get_cmd (grub_command_t cmd);
|
||||
|
||||
void
|
||||
grub_gettext_reread_prefix (const char *val);
|
||||
|
||||
enum grub_human_size_type
|
||||
{
|
||||
GRUB_HUMAN_SIZE_NORMAL,
|
||||
GRUB_HUMAN_SIZE_SHORT,
|
||||
GRUB_HUMAN_SIZE_SPEED,
|
||||
};
|
||||
|
||||
const char *
|
||||
grub_get_human_size (grub_uint64_t size, enum grub_human_size_type type);
|
||||
|
||||
#endif /* ! GRUB_NORMAL_HEADER */
|
@@ -71,7 +71,7 @@ typedef struct ventoy_image_location
|
||||
{
|
||||
ventoy_guid guid;
|
||||
|
||||
/* image sector size, currently this value is always 2048 */
|
||||
/* image sector size, 2048/512 */
|
||||
grub_uint32_t image_sector_size;
|
||||
|
||||
/* disk sector size, normally the value is 512 */
|
||||
@@ -125,7 +125,9 @@ typedef struct ventoy_os_param
|
||||
*/
|
||||
grub_uint8_t vtoy_reserved[32]; // Internal use by ventoy
|
||||
|
||||
grub_uint8_t reserved[31];
|
||||
grub_uint8_t vtoy_disk_signature[4];
|
||||
|
||||
grub_uint8_t reserved[27];
|
||||
}ventoy_os_param;
|
||||
|
||||
|
||||
@@ -219,6 +221,7 @@ typedef struct ventoy_img_chunk_list
|
||||
#define GRUB_FILE_REPLACE_MAGIC 0x1258BEEF
|
||||
|
||||
typedef const char * (*grub_env_get_pf)(const char *name);
|
||||
typedef int (*grub_env_set_pf)(const char *name, const char *val);
|
||||
typedef int (*grub_env_printf_pf)(const char *fmt, ...);
|
||||
|
||||
typedef struct ventoy_grub_param_file_replace
|
||||
@@ -232,6 +235,7 @@ typedef struct ventoy_grub_param_file_replace
|
||||
typedef struct ventoy_grub_param
|
||||
{
|
||||
grub_env_get_pf grub_env_get;
|
||||
grub_env_set_pf grub_env_set;
|
||||
ventoy_grub_param_file_replace file_replace;
|
||||
grub_env_printf_pf grub_env_printf;
|
||||
}ventoy_grub_param;
|
||||
|
@@ -12,19 +12,23 @@ make install
|
||||
PATH=$PATH:$VT_DIR/GRUB2/INSTALL/bin/:$VT_DIR/GRUB2/INSTALL/sbin/
|
||||
|
||||
net_modules_legacy="net tftp http"
|
||||
all_modules_legacy="date drivemap blocklist vga_text ntldr search at_keyboard usb_keyboard gcry_md5 hashsum gzio xzio lzopio lspci pci ext2 xfs ventoy chain read halt iso9660 linux16 test true sleep reboot echo videotest videoinfo videotest_checksum video_colors video_cirrus video_bochs vga vbe video_fb font video gettext extcmd terminal linux minicmd help configfile tr trig boot biosdisk disk ls tar squash4 password_pbkdf2 all_video png jpeg part_gpt part_msdos fat exfat ntfs loopback gzio normal udf gfxmenu gfxterm gfxterm_background gfxterm_menu"
|
||||
all_modules_legacy="date drivemap blocklist newc vga_text ntldr search at_keyboard usb_keyboard gcry_md5 hashsum gzio xzio lzopio lspci pci ext2 xfs ventoy chain read halt iso9660 linux16 test true sleep reboot echo videotest videoinfo videotest_checksum video_colors video_cirrus video_bochs vga vbe video_fb font video gettext extcmd terminal linux minicmd help configfile tr trig boot biosdisk disk ls tar squash4 password_pbkdf2 all_video png jpeg part_gpt part_msdos fat exfat ntfs loopback gzio normal udf gfxmenu gfxterm gfxterm_background gfxterm_menu"
|
||||
|
||||
net_modules_uefi="efinet net tftp http"
|
||||
all_modules_uefi="blocklist ventoy test search at_keyboard usb_keyboard gcry_md5 hashsum gzio xzio lzopio ext2 xfs read halt sleep serial terminfo png password_pbkdf2 gcry_sha512 pbkdf2 part_gpt part_msdos ls tar squash4 loopback part_apple minicmd diskfilter linux relocator jpeg iso9660 udf hfsplus halt acpi mmap gfxmenu video_colors trig bitmap_scale gfxterm bitmap font fat exfat ntfs fshelp efifwsetup reboot echo configfile normal terminal gettext chain priority_queue bufio datetime cat extcmd crypto gzio boot all_video efi_gop efi_uga video_bochs video_cirrus video video_fb gfxterm_background gfxterm_menu"
|
||||
|
||||
all_extra_modules="elf macho offsetio regexp file"
|
||||
all_modules_uefi="blocklist ventoy test newc search at_keyboard usb_keyboard gcry_md5 hashsum gzio xzio lzopio ext2 xfs read halt sleep serial terminfo png password_pbkdf2 gcry_sha512 pbkdf2 part_gpt part_msdos ls tar squash4 loopback part_apple minicmd diskfilter linux relocator jpeg iso9660 udf hfsplus halt acpi mmap gfxmenu video_colors trig bitmap_scale gfxterm bitmap font fat exfat ntfs fshelp efifwsetup reboot echo configfile normal terminal gettext chain priority_queue bufio datetime cat extcmd crypto gzio boot all_video efi_gop efi_uga video_bochs video_cirrus video video_fb gfxterm_background gfxterm_menu"
|
||||
|
||||
if [ "$1" = "uefi" ]; then
|
||||
all_modules="$net_modules_uefi $all_modules_uefi $all_extra_modules "
|
||||
all_modules="$net_modules_uefi $all_modules_uefi "
|
||||
grub-mkimage -v --directory "$VT_DIR/GRUB2/INSTALL/lib/grub/x86_64-efi" --prefix '(,2)/grub' --output "$VT_DIR/INSTALL/EFI/BOOT/grubx64_real.efi" --format 'x86_64-efi' --compression 'auto' $all_modules_uefi 'fat' 'part_msdos'
|
||||
|
||||
#grub-mkimage -v --directory "$VT_DIR/GRUB2/INSTALL/lib/grub/x86_64-efi" -c "$VT_DIR/LiveCD/GRUB/embed.cfg" --prefix '/EFI/boot' --output "$VT_DIR/LiveCD/GRUB/bootx64.efi" --format 'x86_64-efi' --compression 'auto' $all_modules_uefi 'fat' 'part_msdos'
|
||||
else
|
||||
all_modules="$net_modules_legacy $all_modules_legacy "
|
||||
grub-mkimage -v --directory "$VT_DIR/GRUB2/INSTALL/lib/grub/i386-pc" --prefix '(,2)/grub' --output "$VT_DIR/INSTALL/grub/i386-pc/core.img" --format 'i386-pc' --compression 'auto' $all_modules_legacy 'fat' 'part_msdos' 'biosdisk'
|
||||
|
||||
#grub-mkimage -v --directory "$VT_DIR/GRUB2/INSTALL/lib/grub/i386-pc" -c "$VT_DIR/LiveCD/GRUB/embed.cfg" --prefix '/EFI/boot' --output "$VT_DIR/LiveCD/GRUB/cdrom.img" --format 'i386-pc-eltorito' --compression 'auto' $all_modules_legacy 'biosdisk' 'iso9660' 'fat' 'part_msdos'
|
||||
#rm -f $VT_DIR/LiveCD/GRUB/boot_hybrid.img
|
||||
#cp -a $VT_DIR/GRUB2/INSTALL/lib/grub/i386-pc/boot_hybrid.img $VT_DIR/LiveCD/GRUB/boot_hybrid.img
|
||||
fi
|
||||
|
||||
grub-mknetdir --modules="$all_modules" --net-directory=$VT_DIR/GRUB2/PXE --subdir=grub2 --locales=en@quot || exit 1
|
||||
@@ -38,7 +42,7 @@ if [ "$1" = "uefi" ]; then
|
||||
|
||||
#copy other modules
|
||||
ls -1 $VT_DIR/GRUB2/INSTALL/lib/grub/x86_64-efi/ | egrep '\.(lst|mod)$' | while read line; do
|
||||
if ! echo $all_modules | grep -q "${line%.mod} "; then
|
||||
if ! echo $all_modules | grep -q " ${line%.mod} "; then
|
||||
echo "Copy $line ..."
|
||||
rm -f $VT_DIR/INSTALL/grub/x86_64-efi/$line
|
||||
cp -a $VT_DIR/GRUB2/INSTALL/lib/grub/x86_64-efi/$line $VT_DIR/INSTALL/grub/x86_64-efi/
|
||||
@@ -53,7 +57,7 @@ else
|
||||
|
||||
#copy other modules
|
||||
ls -1 $VT_DIR/GRUB2/INSTALL/lib/grub/i386-pc/ | egrep '\.(lst|mod)$' | while read line; do
|
||||
if ! echo $all_modules | grep -q "${line%.mod} "; then
|
||||
if ! echo $all_modules | grep -q " ${line%.mod} "; then
|
||||
echo "Copy $line ..."
|
||||
rm -f $VT_DIR/INSTALL/grub/i386-pc/$line
|
||||
cp -a $VT_DIR/GRUB2/INSTALL/lib/grub/i386-pc/$line $VT_DIR/INSTALL/grub/i386-pc/
|
||||
|
BIN
ICON/forums.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
ICON/logo_128.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
ICON/logo_16.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
ICON/logo_256.png
Normal file
After Width: | Height: | Size: 76 KiB |
BIN
ICON/logo_32.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
ICON/logo_48.png
Normal file
After Width: | Height: | Size: 5.3 KiB |
BIN
ICON/logo_512.png
Normal file
After Width: | Height: | Size: 223 KiB |
BIN
ICON/logo_64.png
Normal file
After Width: | Height: | Size: 7.7 KiB |
BIN
ICON/logo_72.png
Normal file
After Width: | Height: | Size: 9.0 KiB |
@@ -1,4 +1,4 @@
|
||||
#!/ventoy/busybox/tmpsh
|
||||
#!/ventoy/busybox/ash
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
@@ -36,8 +36,25 @@ export SED=$BUSYBOX_PATH/sed
|
||||
export SLEEP=$BUSYBOX_PATH/sleep
|
||||
export HEAD=$BUSYBOX_PATH/head
|
||||
|
||||
$BUSYBOX_PATH/tmpxz -d $BUSYBOX_PATH/busybox.xz
|
||||
$BUSYBOX_PATH/busybox --install $BUSYBOX_PATH
|
||||
if [ -e $BUSYBOX_PATH/64h ]; then
|
||||
$BUSYBOX_PATH/xzminidec32 < $BUSYBOX_PATH/busybox32.xz > $BUSYBOX_PATH/busybox
|
||||
$BUSYBOX_PATH/vtchmod32 $BUSYBOX_PATH/busybox
|
||||
else
|
||||
$BUSYBOX_PATH/xzminidec64 < $BUSYBOX_PATH/busybox64.xz > $BUSYBOX_PATH/busybox
|
||||
if [ -s $BUSYBOX_PATH/busybox ]; then
|
||||
$BUSYBOX_PATH/vtchmod64 $BUSYBOX_PATH/busybox
|
||||
else
|
||||
$BUSYBOX_PATH/xzminidec64_uclibc < $BUSYBOX_PATH/busybox64.xz > $BUSYBOX_PATH/busybox
|
||||
$BUSYBOX_PATH/vtchmod64_uclibc $BUSYBOX_PATH/busybox
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -e $BUSYBOX_PATH/busybox ]; then
|
||||
$BUSYBOX_PATH/busybox --install $BUSYBOX_PATH
|
||||
else
|
||||
$BUSYBOX_PATH/tmpxz -d $BUSYBOX_PATH/busybox32.xz
|
||||
$BUSYBOX_PATH/busybox32 --install $BUSYBOX_PATH
|
||||
fi
|
||||
|
||||
export PATH=$BUSYBOX_PATH/:$VTOY_PATH/tool
|
||||
|
||||
@@ -54,14 +71,29 @@ if [ -z "$VTOY_REDT_BUG" ]; then
|
||||
fi
|
||||
|
||||
cd $VTOY_PATH
|
||||
xz -d ventoy.sh.xz
|
||||
xz -d ventoy_chain.sh.xz
|
||||
xz -d ventoy_loop.sh.xz
|
||||
|
||||
if [ -n "$VTOY_REDT_BUG" ]; then
|
||||
xz -d -c hook.cpio.xz | cpio -idm
|
||||
xz -d -c tool.cpio.xz | cpio -idm
|
||||
xz -d -c loop.cpio.xz | cpio -idm
|
||||
else
|
||||
xz -d -c hook.cpio.xz | cpio -idm 2>>$VTLOG
|
||||
xz -d -c tool.cpio.xz | cpio -idm 2>>$VTLOG
|
||||
xz -d -c loop.cpio.xz | cpio -idm 2>>$VTLOG
|
||||
fi
|
||||
|
||||
if [ -e $BUSYBOX_PATH/64h ]; then
|
||||
echo "Use busybox32 toolkit ..." >>$VTLOG
|
||||
ln -s $BUSYBOX_PATH/xzminidec32 $BUSYBOX_PATH/xzminidec
|
||||
ln -s $VTOY_PATH/tool/dmsetup32 $VTOY_PATH/tool/dmsetup
|
||||
ln -s $VTOY_PATH/tool/lunzip32 $VTOY_PATH/tool/lunzip
|
||||
else
|
||||
echo "Use busybox64 toolkit ..." >>$VTLOG
|
||||
ln -s $BUSYBOX_PATH/xzminidec64 $BUSYBOX_PATH/xzminidec
|
||||
ln -s $VTOY_PATH/tool/dmsetup64 $VTOY_PATH/tool/dmsetup
|
||||
ln -s $VTOY_PATH/tool/lunzip64 $VTOY_PATH/tool/lunzip
|
||||
fi
|
||||
|
||||
rm -f *.xz
|
||||
|
BIN
IMG/cpio/ventoy/busybox/64h
Normal file
BIN
IMG/cpio/ventoy/busybox/busybox64.xz
Normal file
BIN
IMG/cpio/ventoy/busybox/vtchmod32
Normal file
BIN
IMG/cpio/ventoy/busybox/vtchmod64
Normal file
BIN
IMG/cpio/ventoy/busybox/vtchmod64_uclibc
Normal file
BIN
IMG/cpio/ventoy/busybox/xzminidec64
Normal file
BIN
IMG/cpio/ventoy/busybox/xzminidec64_uclibc
Normal file
@@ -59,7 +59,15 @@ mkdir -p $VTOY_PATH/mnt
|
||||
mount /vt_modloop $VTOY_PATH/mnt
|
||||
|
||||
KoModPath=$(find $VTOY_PATH/mnt/ -name 'dm-mod.ko*')
|
||||
vtlog "insmod $KoModPath"
|
||||
vtlog "KoModPath=$KoModPath"
|
||||
|
||||
if modinfo $KoModPath | grep -q 'depend.*dax'; then
|
||||
vtlog "First install dax mod ..."
|
||||
DaxModPath=$(echo $KoModPath | sed 's#md/dm-mod#dax/dax#')
|
||||
vtlog "insmod $DaxModPath"
|
||||
insmod $DaxModPath
|
||||
fi
|
||||
|
||||
insmod $KoModPath
|
||||
|
||||
umount $VTOY_PATH/mnt
|
||||
|
@@ -35,14 +35,32 @@ fi
|
||||
|
||||
ventoy_udev_disk_common_hook "${vtdiskname#/dev/}2" "noreplace"
|
||||
|
||||
blkdev_num=$($VTOY_PATH/tool/dmsetup ls | grep ventoy | sed 's/.*(\([0-9][0-9]*\),.*\([0-9][0-9]*\).*/\1:\2/')
|
||||
vtDM=$(ventoy_find_dm_id ${blkdev_num})
|
||||
vtlog "blkdev_num=$blkdev_num vtDM=$vtDM ..."
|
||||
|
||||
while [ -n "Y" ]; do
|
||||
if [ -b /dev/$vtDM ]; then
|
||||
break
|
||||
else
|
||||
sleep 0.3
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -n "$1" ]; then
|
||||
blkdev_num=$($VTOY_PATH/tool/dmsetup ls | grep ventoy | sed 's/.*(\([0-9][0-9]*\),.*\([0-9][0-9]*\).*/\1:\2/')
|
||||
vtDM=$(ventoy_find_dm_id ${blkdev_num})
|
||||
|
||||
vtlog "ln -s /dev/$vtDM $1"
|
||||
ln -s /dev/$vtDM "$1"
|
||||
else
|
||||
vtLABEL=$($BUSYBOX_PATH/blkid /dev/$vtDM | $SED 's/.*LABEL="\([^"]*\)".*/\1/')
|
||||
vtlog "vtLABEL is $vtLABEL"
|
||||
|
||||
if [ -z "$vtLABEL" ]; then
|
||||
vtLABEL=$($SED "s/.*label=\([^ ]*\)/\1/" /proc/cmdline)
|
||||
vtlog "vtLABEL is $vtLABEL from cmdline"
|
||||
fi
|
||||
|
||||
ln -s /dev/$vtDM "/dev/disk/by-label/$vtLABEL"
|
||||
fi
|
||||
|
||||
# OK finish
|
||||
set_ventoy_hook_finish
|
||||
|
||||
|
@@ -21,11 +21,23 @@
|
||||
|
||||
if $GREP -q '^"$mount_handler"' /init; then
|
||||
echo 'use mount_handler ...' >> $VTLOG
|
||||
$SED "/^\"\$mount_handler\"/i\ $BUSYBOX_PATH/sh $VTOY_PATH/hook/arch/ventoy-disk.sh \"\$archisodevice\"" -i /init
|
||||
|
||||
if [ -f /hooks/archiso ]; then
|
||||
$SED '/while ! poll_device "${dev}"/a\ if /ventoy/busybox/sh /ventoy/hook/arch/ventoy-timeout.sh ${dev}; then break; fi' -i /hooks/archiso
|
||||
vthookfile=/hooks/archiso
|
||||
|
||||
if [ -e /hooks/miso ]; then
|
||||
vthookfile=/hooks/miso
|
||||
$SED "/^\"\$mount_handler\"/i\ $BUSYBOX_PATH/sh $VTOY_PATH/hook/arch/ventoy-disk.sh \"\$misodevice\"" -i /init
|
||||
elif [ -e /hooks/artix ]; then
|
||||
vthookfile=/hooks/artix
|
||||
$SED "/^\"\$mount_handler\"/i\ $BUSYBOX_PATH/sh $VTOY_PATH/hook/arch/ventoy-disk.sh \"\$artixdevice\"" -i /init
|
||||
else
|
||||
$SED "/^\"\$mount_handler\"/i\ $BUSYBOX_PATH/sh $VTOY_PATH/hook/arch/ventoy-disk.sh \"\$archisodevice\"" -i /init
|
||||
fi
|
||||
|
||||
if [ -f $vthookfile ]; then
|
||||
$SED '/while ! poll_device "${dev}"/a\ if /ventoy/busybox/sh /ventoy/hook/arch/ventoy-timeout.sh ${dev}; then break; fi' -i $vthookfile
|
||||
fi
|
||||
|
||||
elif $GREP -q '^KEEP_SEARCHING' /init; then
|
||||
echo 'KEEP_SEARCHING found ...' >> $VTLOG
|
||||
$SED "/^KEEP_SEARCHING/i\ $BUSYBOX_PATH/sh $VTOY_PATH/hook/arch/ovios-disk.sh " -i /init
|
||||
|
51
IMG/cpio/ventoy/hook/aryalinux/disk_hook.sh
Normal file
@@ -0,0 +1,51 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. /ventoy/hook/ventoy-hook-lib.sh
|
||||
|
||||
VTPATH_OLD=$PATH; PATH=$BUSYBOX_PATH:$VTOY_PATH/tool:$PATH
|
||||
|
||||
mkdir /sys
|
||||
mount -t sysfs sys /sys
|
||||
|
||||
wait_for_usb_disk_ready
|
||||
|
||||
vtdiskname=$(get_ventoy_disk_name)
|
||||
if [ "$vtdiskname" = "unknown" ]; then
|
||||
vtlog "ventoy disk not found"
|
||||
PATH=$VTPATH_OLD
|
||||
exit 0
|
||||
fi
|
||||
|
||||
ventoy_udev_disk_common_hook "${vtdiskname#/dev/}2" "noreplace"
|
||||
|
||||
blkdev_num=$($VTOY_PATH/tool/dmsetup ls | grep ventoy | sed 's/.*(\([0-9][0-9]*\),.*\([0-9][0-9]*\).*/\1:\2/')
|
||||
blkdev_num_mknod=$($VTOY_PATH/tool/dmsetup ls | grep ventoy | sed 's/.*(\([0-9][0-9]*\),.*\([0-9][0-9]*\).*/\1 \2/')
|
||||
vtDM=$(ventoy_find_dm_id ${blkdev_num})
|
||||
|
||||
vtlog "blkdev_num=$blkdev_num blkdev_num_mknod=$blkdev_num_mknod vtDM=$vtDM"
|
||||
|
||||
if [ -b /dev/$vtDM ]; then
|
||||
vtlog "dev already exist ..."
|
||||
else
|
||||
vtlog "mknode dev ..."
|
||||
mknod -m 660 /dev/$vtDM b $blkdev_num_mknod
|
||||
fi
|
||||
|
||||
PATH=$VTPATH_OLD
|
26
IMG/cpio/ventoy/hook/aryalinux/ventoy-hook.sh
Normal file
@@ -0,0 +1,26 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. $VTOY_PATH/hook/ventoy-os-lib.sh
|
||||
|
||||
$BUSYBOX_PATH/mkdir /dev
|
||||
$BUSYBOX_PATH/mknod -m 660 /dev/console b 5 1
|
||||
|
||||
$SED "/for device in/i $BUSYBOX_PATH/sh $VTOY_PATH/hook/aryalinux/disk_hook.sh" -i /init
|
||||
#$SED "/for device in/i exec $BUSYBOX_PATH/sh" -i /init
|
25
IMG/cpio/ventoy/hook/blackPanther/ventoy-hook.sh
Normal file
@@ -0,0 +1,25 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. $VTOY_PATH/hook/ventoy-os-lib.sh
|
||||
|
||||
ventoy_set_inotify_script blackPanther/ventoy-inotifyd-hook.sh
|
||||
$BUSYBOX_PATH/cp -a $VTOY_PATH/hook/blackPanther/ventoy-inotifyd-start.sh /lib/dracut/hooks/pre-udev/00-ventoy-inotifyd-start.sh
|
||||
|
||||
$SED "s#printf\(.*\)\$CMDLINE#printf\1 root=/dev/dm-0 \$CMDLINE root=/dev/dm-0#" -i /lib/dracut-lib.sh
|
46
IMG/cpio/ventoy/hook/blackPanther/ventoy-inotifyd-hook.sh
Normal file
@@ -0,0 +1,46 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. /ventoy/hook/ventoy-hook-lib.sh
|
||||
|
||||
if is_ventoy_hook_finished; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
VTPATH_OLD=$PATH; PATH=$BUSYBOX_PATH:$VTOY_PATH/tool:$PATH
|
||||
|
||||
if is_inotify_ventoy_part $3; then
|
||||
|
||||
vtlog "##### INOTIFYD: $2/$3 is created (YES) ..."
|
||||
|
||||
vtlog "find ventoy partition ..."
|
||||
$BUSYBOX_PATH/sh $VTOY_PATH/hook/default/udev_disk_hook.sh $3 noreplace
|
||||
|
||||
blkdev_num_dev=$($VTOY_PATH/tool/dmsetup ls | grep ventoy | sed 's/.*(\([0-9][0-9]*\),.*\([0-9][0-9]*\).*/\1 \2/')
|
||||
if ! [ -e /dev/dm-0 ]; then
|
||||
mknod -m 660 /dev/dm-0 b $blkdev_num_dev
|
||||
fi
|
||||
blackPanther-root /dev/dm-0
|
||||
|
||||
set_ventoy_hook_finish
|
||||
else
|
||||
vtlog "##### INOTIFYD: $2/$3 is created (NO) ..."
|
||||
fi
|
||||
|
||||
PATH=$VTPATH_OLD
|
32
IMG/cpio/ventoy/hook/blackPanther/ventoy-inotifyd-start.sh
Normal file
@@ -0,0 +1,32 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. /ventoy/hook/ventoy-hook-lib.sh
|
||||
|
||||
vtHook=$($CAT $VTOY_PATH/inotifyd-hook-script.txt)
|
||||
|
||||
vtdisk=$(get_ventoy_disk_name)
|
||||
if [ "$vtdisk" = "unknown" ]; then
|
||||
vtlog "... start inotifyd listen $vtHook ..."
|
||||
$BUSYBOX_PATH/nohup $VTOY_PATH/tool/inotifyd $vtHook /dev:n 2>&- &
|
||||
else
|
||||
vtlog "... $vtdisk already exist ..."
|
||||
$BUSYBOX_PATH/sh $vtHook n /dev "${vtdisk#/dev/}2"
|
||||
fi
|
||||
|
40
IMG/cpio/ventoy/hook/crux/disk_hook.sh
Normal file
@@ -0,0 +1,40 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. /ventoy/hook/ventoy-hook-lib.sh
|
||||
|
||||
for i in 0 1 2 3 4 5 6 7 8 9; do
|
||||
vtdiskname=$(get_ventoy_disk_name)
|
||||
if [ "$vtdiskname" = "unknown" ]; then
|
||||
vtlog "wait for disk ..."
|
||||
$SLEEP 3
|
||||
else
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
ventoy_extract_vtloopex ${vtdiskname}2 crux
|
||||
|
||||
vtLoopExDir=$VTOY_PATH/vtloopex/crux/vtloopex
|
||||
$BUSYBOX_PATH/xz -d $vtLoopExDir/dm-mod/$(uname -r)/64/dax.ko.xz
|
||||
$BUSYBOX_PATH/xz -d $vtLoopExDir/dm-mod/$(uname -r)/64/dm-mod.ko.xz
|
||||
$BUSYBOX_PATH/insmod $vtLoopExDir/dm-mod/$(uname -r)/64/dax.ko
|
||||
$BUSYBOX_PATH/insmod $vtLoopExDir/dm-mod/$(uname -r)/64/dm-mod.ko
|
||||
|
||||
ventoy_udev_disk_common_hook "${vtdiskname#/dev/}2"
|
22
IMG/cpio/ventoy/hook/crux/ventoy-hook.sh
Normal file
@@ -0,0 +1,22 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. $VTOY_PATH/hook/ventoy-os-lib.sh
|
||||
|
||||
$SED "/find_and_mount_media.*(/a\ $BUSYBOX_PATH/sh $VTOY_PATH/hook/crux/disk_hook.sh" -i /init
|
36
IMG/cpio/ventoy/hook/daphile/disk_hook.sh
Normal file
@@ -0,0 +1,36 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. /ventoy/hook/ventoy-hook-lib.sh
|
||||
|
||||
# Just for KVM test enviroment
|
||||
$BUSYBOX_PATH/modprobe virtio_blk 2>/dev/null
|
||||
$BUSYBOX_PATH/modprobe virtio_pci 2>/dev/null
|
||||
|
||||
for i in 0 1 2 3 4 5 6 7 8 9; do
|
||||
vtdiskname=$(get_ventoy_disk_name)
|
||||
if [ "$vtdiskname" = "unknown" ]; then
|
||||
vtlog "wait for disk ..."
|
||||
$SLEEP 2
|
||||
else
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
ventoy_udev_disk_common_hook "${vtdiskname#/dev/}2" "noreplace"
|
24
IMG/cpio/ventoy/hook/daphile/ventoy-hook.sh
Normal file
@@ -0,0 +1,24 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. $VTOY_PATH/hook/ventoy-os-lib.sh
|
||||
|
||||
$SED "/mount_boot /i\ $BUSYBOX_PATH/sh $VTOY_PATH/hook/gentoo/disk_hook.sh" -i /init
|
||||
|
||||
$SED "s#'\.\*/block/mmcblk[^ ]*'#'\.\*/block/dm-[0-9]*'#" -i /init
|
@@ -60,3 +60,18 @@ if [ -f $VTOY_PATH/autoinstall ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
#for ARMA aka Omoikane
|
||||
if [ -f /mod.img ] && [ -f /mod/fs/cramfs.ko ]; then
|
||||
echo "mount mod.img and install dm-mod.ko" >> $VTLOG
|
||||
$BUSYBOX_PATH/insmod /mod/fs/cramfs.ko
|
||||
|
||||
$BUSYBOX_PATH/mkdir $VTOY_PATH/modmnt
|
||||
$BUSYBOX_PATH/mount /mod.img $VTOY_PATH/modmnt
|
||||
$BUSYBOX_PATH/insmod $VTOY_PATH/modmnt/md/dm-mod.ko
|
||||
$BUSYBOX_PATH/umount $VTOY_PATH/modmnt
|
||||
|
||||
$BUSYBOX_PATH/rmmod cramfs
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
43
IMG/cpio/ventoy/hook/debian/mll-disk.sh
Normal file
@@ -0,0 +1,43 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. /ventoy/hook/ventoy-hook-lib.sh
|
||||
|
||||
if is_ventoy_hook_finished; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
vtlog "####### $0 $* ########"
|
||||
|
||||
VTPATH_OLD=$PATH; PATH=$BUSYBOX_PATH:$VTOY_PATH/tool:$PATH
|
||||
|
||||
wait_for_usb_disk_ready
|
||||
|
||||
vtdiskname=$(get_ventoy_disk_name)
|
||||
if [ "$vtdiskname" = "unknown" ]; then
|
||||
vtlog "ventoy disk not found"
|
||||
PATH=$VTPATH_OLD
|
||||
exit 0
|
||||
fi
|
||||
|
||||
ventoy_udev_disk_common_hook "${vtdiskname#/dev/}2" "noreplace"
|
||||
|
||||
PATH=$VTPATH_OLD
|
||||
|
||||
set_ventoy_hook_finish
|
21
IMG/cpio/ventoy/hook/debian/mll-hook.sh
Normal file
@@ -0,0 +1,21 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
$SED "/^for DEVICE in/i\ $BUSYBOX_PATH/sh $VTOY_PATH/hook/debian/mll-disk.sh" -i /etc/02_overlay.sh
|
||||
|
@@ -20,5 +20,11 @@
|
||||
$SED "s#.*livefs_root=.*find_livefs.*#$BUSYBOX_PATH/mount -t iso9660 /dev/mapper/ventoy \$mountpoint; livefs_root=\$mountpoint#" -i /usr/lib/live/boot/9990-main.sh
|
||||
$SED "s#.*livefs_root=.*find_livefs.*#$BUSYBOX_PATH/mount -t iso9660 /dev/mapper/ventoy \$mountpoint; livefs_root=\$mountpoint#" -i /usr/bin/boot/9990-main.sh
|
||||
|
||||
ventoy_systemd_udevd_work_around
|
||||
ventoy_add_udev_rule "$VTOY_PATH/hook/debian/udev_disk_hook.sh %k"
|
||||
if [ -e /init ] && $GREP -q '^mountroot$' /init; then
|
||||
echo "Here before mountroot ..." >> $VTLOG
|
||||
$SED "/^mountroot$/i\\$BUSYBOX_PATH/sh $VTOY_PATH/hook/debian/disk_mount_hook.sh" -i /init
|
||||
else
|
||||
echo "Use default hook ..." >> $VTLOG
|
||||
ventoy_systemd_udevd_work_around
|
||||
ventoy_add_udev_rule "$VTOY_PATH/hook/debian/udev_disk_hook.sh %k"
|
||||
fi
|
||||
|
@@ -43,6 +43,18 @@ ventoy_os_install_dmsetup() {
|
||||
# install md-modules
|
||||
LINE=$($GREP ' md-modules.*\.udeb' $VTOY_PATH/iso_file_list)
|
||||
if [ $? -eq 0 ]; then
|
||||
LINTCNT=$($GREP -c ' md-modules.*\.udeb' $VTOY_PATH/iso_file_list)
|
||||
if [ $LINTCNT -gt 1 ]; then
|
||||
vtlog "more than one pkgs, need to filter..."
|
||||
VER=$($BUSYBOX_PATH/uname -r)
|
||||
|
||||
LINE=$($GREP ' md-modules.*\.udeb' $VTOY_PATH/iso_file_list | $GREP $VER)
|
||||
LINTCNT=$($GREP ' md-modules.*\.udeb' $VTOY_PATH/iso_file_list | $GREP -c $VER)
|
||||
if [ $LINTCNT -gt 1 ]; then
|
||||
vtlog "Still more than one pkgs, use the first one..."
|
||||
LINE=$($GREP ' md-modules.*\.udeb' $VTOY_PATH/iso_file_list | $GREP -m1 $VER)
|
||||
fi
|
||||
fi
|
||||
install_udeb_from_line "$LINE" ${vt_usb_disk}
|
||||
fi
|
||||
|
||||
@@ -83,6 +95,8 @@ if is_ventoy_hook_finished || not_ventoy_disk "${1:0:-1}"; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
vtlog "==== $0 $* ===="
|
||||
|
||||
dmsetup_path=$(ventoy_find_bin_path dmsetup)
|
||||
if [ -z "$dmsetup_path" ]; then
|
||||
ventoy_os_install_dmsetup "/dev/${1:0:-1}"
|
||||
|
@@ -35,6 +35,8 @@ ventoy_get_debian_distro() {
|
||||
else
|
||||
echo 'puppy'; return
|
||||
fi
|
||||
elif $GREP -m1 -q 'Minimal.*Linux.*Live' /init; then
|
||||
echo 'mll'; return
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -64,6 +66,10 @@ ventoy_get_debian_distro() {
|
||||
echo 'linuxconsole'; return
|
||||
fi
|
||||
|
||||
if $GREP -q 'vyos' /proc/version; then
|
||||
echo 'vyos'; return
|
||||
fi
|
||||
|
||||
echo 'default'
|
||||
}
|
||||
|
||||
@@ -72,10 +78,10 @@ DISTRO=$(ventoy_get_debian_distro)
|
||||
echo "##### distribution = $DISTRO ######" >> $VTLOG
|
||||
. $VTOY_PATH/hook/debian/${DISTRO}-hook.sh
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if [ -f /bin/env2debconf ]; then
|
||||
$SED "1a /bin/sh $VTOY_PATH/hook/debian/ventoy_env2debconf.sh" -i /bin/env2debconf
|
||||
$SED "s#in *\$(set)#in \$(cat /ventoy/envset)#" -i /bin/env2debconf
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
33
IMG/cpio/ventoy/hook/debian/ventoy_env2debconf.sh
Normal file
@@ -0,0 +1,33 @@
|
||||
#!/bin/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
PATH=$PATH:/ventoy/busybox
|
||||
|
||||
set > /ventoy/tmpenvset
|
||||
|
||||
for i in $(cat /proc/cmdline); do
|
||||
if echo $i | grep -q "="; then
|
||||
vtKey=${i%=*}
|
||||
if ! grep -q "^$vtKey" /ventoy/tmpenvset; then
|
||||
echo $i >> /ventoy/envset
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
cat /ventoy/tmpenvset >> /ventoy/envset
|
49
IMG/cpio/ventoy/hook/debian/vyos-disk.sh
Normal file
@@ -0,0 +1,49 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. /ventoy/hook/ventoy-hook-lib.sh
|
||||
|
||||
if is_ventoy_hook_finished; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
vtlog "####### $0 $* ########"
|
||||
|
||||
VTPATH_OLD=$PATH; PATH=$BUSYBOX_PATH:$VTOY_PATH/tool:$PATH
|
||||
|
||||
wait_for_usb_disk_ready
|
||||
|
||||
vtdiskname=$(get_ventoy_disk_name)
|
||||
if [ "$vtdiskname" = "unknown" ]; then
|
||||
vtlog "ventoy disk not found"
|
||||
PATH=$VTPATH_OLD
|
||||
exit 0
|
||||
fi
|
||||
|
||||
mkdir -p /live/vtoyfuse /live/vtoyiso
|
||||
|
||||
modprobe fuse
|
||||
vtoydm -p -f $VTOY_PATH/ventoy_image_map -d $vtdiskname > $VTOY_PATH/ventoy_dm_table
|
||||
vtoy_fuse_iso -f $VTOY_PATH/ventoy_dm_table -m /live/vtoyfuse
|
||||
|
||||
mount -t iso9660 /live/vtoyfuse/ventoy.iso /live/vtoyiso
|
||||
|
||||
PATH=$VTPATH_OLD
|
||||
|
||||
set_ventoy_hook_finish
|
25
IMG/cpio/ventoy/hook/debian/vyos-hook.sh
Normal file
@@ -0,0 +1,25 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
if [ -e /init ] && $GREP -q '^mountroot$' /init; then
|
||||
echo "Here before mountroot ..." >> $VTLOG
|
||||
$SED "/^mountroot$/i\\$BUSYBOX_PATH/sh $VTOY_PATH/hook/debian/vyos-disk.sh" -i /init
|
||||
$SED "/^mountroot$/i\\export LIVE_MEDIA=/live/vtoyiso" -i /init
|
||||
#$SED "/^mountroot$/i\\exec /ventoy/busybox/sh" -i /init
|
||||
fi
|
150
IMG/cpio/ventoy/hook/default/10-dm.rules
Normal file
@@ -0,0 +1,150 @@
|
||||
# Copyright (C) 2009 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of LVM2.
|
||||
|
||||
# Udev rules for device-mapper devices.
|
||||
#
|
||||
# These rules create a DM control node in /dev/mapper directory.
|
||||
# The rules also create nodes named dm-x (x is a number) in /dev
|
||||
# directory and symlinks to these nodes with names given by
|
||||
# the actual DM names. Some udev environment variables are set
|
||||
# for use in later rules:
|
||||
# DM_NAME - actual DM device's name
|
||||
# DM_UUID - UUID set for DM device (blank if not specified)
|
||||
# DM_SUSPENDED - suspended state of DM device (0 or 1)
|
||||
# DM_UDEV_RULES_VSN - DM udev rules version
|
||||
#
|
||||
# These rules cover only basic device-mapper functionality in udev.
|
||||
#
|
||||
# Various DM subsystems may contain further subsystem-specific rules
|
||||
# in 11-dm-<subsystem_name>.rules which should be installed together
|
||||
# with the DM subsystem and which extend these basic rules.
|
||||
# For example:
|
||||
# 11-dm-lvm.rules for LVM subsystem
|
||||
# 11-dm-mpath.rules for multipath subsystem (since version 0.6.0, recommended!)
|
||||
#
|
||||
# Even more specific rules may be required by subsystems so always
|
||||
# check subsystem's upstream repository for recent set of rules.
|
||||
# Also, keep in mind that recent rules may also require recent
|
||||
# subsystem-specific binaries.
|
||||
|
||||
KERNEL=="device-mapper", NAME="mapper/control"
|
||||
|
||||
SUBSYSTEM!="block", GOTO="dm_end"
|
||||
KERNEL!="dm-[0-9]*", GOTO="dm_end"
|
||||
|
||||
|
||||
# Device created, major and minor number assigned - "add" event generated.
|
||||
# Table loaded - no event generated.
|
||||
# Device resumed (or renamed) - "change" event generated.
|
||||
# Device removed - "remove" event generated.
|
||||
#
|
||||
# The dm-X nodes are always created, even on "add" event, we can't suppress
|
||||
# that (the node is created even earlier with devtmpfs). All the symlinks
|
||||
# (e.g. /dev/mapper) are created in right time after a device has its table
|
||||
# loaded and is properly resumed. For this reason, direct use of dm-X nodes
|
||||
# is not recommended.
|
||||
ACTION!="add|change", GOTO="dm_end"
|
||||
|
||||
# Decode udev control flags and set environment variables appropriately.
|
||||
# These flags are encoded in DM_COOKIE variable that was introduced in
|
||||
# kernel version 2.6.31. Therefore, we can use this feature with
|
||||
# kernels >= 2.6.31 only. Cookie is not decoded for remove event.
|
||||
ENV{DM_COOKIE}=="?*", IMPORT{program}="/usr/sbin/dmsetup udevflags $env{DM_COOKIE}"
|
||||
|
||||
# Rule out easy-to-detect inappropriate events first.
|
||||
ENV{DISK_RO}=="1", GOTO="dm_disable"
|
||||
|
||||
# There is no cookie set nor any flags encoded in events not originating
|
||||
# in libdevmapper so we need to detect this and try to behave correctly.
|
||||
# For such spurious events, regenerate all flags from current udev database content
|
||||
# (this information would normally be inaccessible for spurious ADD and CHANGE events).
|
||||
ENV{DM_UDEV_PRIMARY_SOURCE_FLAG}=="1", ENV{DM_ACTIVATION}="1", GOTO="dm_flags_done"
|
||||
IMPORT{db}="DM_UDEV_DISABLE_DM_RULES_FLAG"
|
||||
IMPORT{db}="DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG"
|
||||
IMPORT{db}="DM_UDEV_DISABLE_DISK_RULES_FLAG"
|
||||
IMPORT{db}="DM_UDEV_DISABLE_OTHER_RULES_FLAG"
|
||||
IMPORT{db}="DM_UDEV_LOW_PRIORITY_FLAG"
|
||||
IMPORT{db}="DM_UDEV_DISABLE_LIBRARY_FALLBACK_FLAG"
|
||||
IMPORT{db}="DM_UDEV_PRIMARY_SOURCE_FLAG"
|
||||
IMPORT{db}="DM_UDEV_FLAG7"
|
||||
IMPORT{db}="DM_UDEV_RULES_VSN"
|
||||
LABEL="dm_flags_done"
|
||||
|
||||
# Normally, we operate on "change" events. But when coldplugging, there's an
|
||||
# "add" event present. We have to recognize this and do our actions in this
|
||||
# particular situation, too. Also, we don't want the nodes to be created
|
||||
# prematurely on "add" events while not coldplugging. We check
|
||||
# DM_UDEV_PRIMARY_SOURCE_FLAG to see if the device was activated correctly
|
||||
# before and if not, we ignore the "add" event totally. This way we can support
|
||||
# udev triggers generating "add" events (e.g. "udevadm trigger --action=add" or
|
||||
# "echo add > /sys/block/<dm_device>/uevent"). The trigger with "add" event is
|
||||
# also used at boot to reevaluate udev rules for all existing devices activated
|
||||
# before (e.g. in initrd). If udev is used in initrd, we require the udev init
|
||||
# script to not remove the existing udev database so we can reuse the information
|
||||
# stored at the time of device activation in the initrd.
|
||||
ACTION!="add", GOTO="dm_no_coldplug"
|
||||
ENV{DM_UDEV_RULES_VSN}!="1", ENV{DM_UDEV_PRIMARY_SOURCE_FLAG}!="1", GOTO="dm_disable"
|
||||
ENV{DM_ACTIVATION}="1"
|
||||
LABEL="dm_no_coldplug"
|
||||
|
||||
# Putting it together, following table is used to recognize genuine and spurious events.
|
||||
# N.B. Spurious events are generated based on use of the WATCH udev
|
||||
# rule or by triggering an event manually by "udevadm trigger" call
|
||||
# or by "echo <event_name> > /sys/block/dm-X/uevent".
|
||||
#
|
||||
# EVENT DM_UDEV_PRIMARY_SOURCE_FLAG DM_ACTIVATION
|
||||
# ======================================================================
|
||||
# add event (genuine) 0 0
|
||||
# change event (genuine) 1 1
|
||||
# add event (spurious)
|
||||
# |_ dev still not active 0 0
|
||||
# \_ dev already active 1 1
|
||||
# change event (spurious)
|
||||
# |_ dev still not active 0 0
|
||||
# \_ dev already active 1 0
|
||||
|
||||
# "dm" sysfs subdirectory is available in newer versions of DM
|
||||
# only (kernels >= 2.6.29). We have to check for its existence
|
||||
# and use dmsetup tool instead to get the DM name, uuid and
|
||||
# suspended state if the "dm" subdirectory is not present.
|
||||
# The "suspended" item was added even later (kernels >= 2.6.31),
|
||||
# so we also have to call dmsetup if the kernel version used
|
||||
# is in between these releases.
|
||||
TEST=="dm", ENV{DM_NAME}="$attr{dm/name}", ENV{DM_UUID}="$attr{dm/uuid}", ENV{DM_SUSPENDED}="$attr{dm/suspended}"
|
||||
TEST!="dm", IMPORT{program}="/usr/sbin/dmsetup info -j %M -m %m -c --nameprefixes --noheadings --rows -o name,uuid,suspended"
|
||||
ENV{DM_SUSPENDED}!="?*", IMPORT{program}="/usr/sbin/dmsetup info -j %M -m %m -c --nameprefixes --noheadings --rows -o suspended"
|
||||
|
||||
# dmsetup tool provides suspended state information in textual
|
||||
# form with values "Suspended"/"Active". We translate it to
|
||||
# 0/1 respectively to be consistent with sysfs values.
|
||||
ENV{DM_SUSPENDED}=="Active", ENV{DM_SUSPENDED}="0"
|
||||
ENV{DM_SUSPENDED}=="Suspended", ENV{DM_SUSPENDED}="1"
|
||||
|
||||
# This variable provides a reliable way to check that device-mapper
|
||||
# rules were installed. It means that all needed variables are set
|
||||
# by these rules directly so there's no need to acquire them again
|
||||
# later. Other rules can alternate the functionality based on this
|
||||
# fact (e.g. fallback to rules that behave correctly even without
|
||||
# these rules installed). It also provides versioning for any
|
||||
# possible future changes.
|
||||
# VSN 1 - original rules
|
||||
# VSN 2 - add support for synthesized events
|
||||
ENV{DM_UDEV_RULES_VSN}="2"
|
||||
|
||||
ENV{DM_UDEV_DISABLE_DM_RULES_FLAG}!="1", ENV{DM_NAME}=="?*", SYMLINK+="mapper/$env{DM_NAME}"
|
||||
|
||||
# Avoid processing and scanning a DM device in the other (foreign)
|
||||
# rules if it is in suspended state. However, we still keep 'disk'
|
||||
# and 'DM subsystem' related rules enabled in this case.
|
||||
ENV{DM_SUSPENDED}=="1", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1"
|
||||
|
||||
GOTO="dm_end"
|
||||
|
||||
LABEL="dm_disable"
|
||||
ENV{DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG}="1"
|
||||
ENV{DM_UDEV_DISABLE_DISK_RULES_FLAG}="1"
|
||||
ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1"
|
||||
OPTIONS:="nowatch"
|
||||
|
||||
LABEL="dm_end"
|
@@ -22,3 +22,12 @@
|
||||
ventoy_systemd_udevd_work_around
|
||||
|
||||
ventoy_add_udev_rule "$VTOY_PATH/hook/default/udev_disk_hook.sh %k"
|
||||
|
||||
if [ -f /init ]; then
|
||||
vtSize=$($BUSYBOX_PATH/stat -c '%s' /init)
|
||||
if ! [ -L /init ]; then
|
||||
if [ $vtSize -eq 0 ]; then
|
||||
rm -f /init
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
41
IMG/cpio/ventoy/hook/dragora/disk_hook.sh
Normal file
@@ -0,0 +1,41 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. /ventoy/hook/ventoy-hook-lib.sh
|
||||
|
||||
VTPATH_OLD=$PATH; PATH=$BUSYBOX_PATH:$VTOY_PATH/tool:$PATH
|
||||
|
||||
wait_for_usb_disk_ready
|
||||
|
||||
vtdiskname=$(get_ventoy_disk_name)
|
||||
if [ "$vtdiskname" = "unknown" ]; then
|
||||
vtlog "ventoy disk not found"
|
||||
PATH=$VTPATH_OLD
|
||||
exit 0
|
||||
fi
|
||||
|
||||
ventoy_extract_vtloopex ${vtdiskname}2 dragora
|
||||
vtLoopExDir=$VTOY_PATH/vtloopex/dragora/vtloopex
|
||||
$BUSYBOX_PATH/xz -d $vtLoopExDir/dm-mod/$(uname -r)/64/dm-mod.ko.xz
|
||||
$BUSYBOX_PATH/insmod $vtLoopExDir/dm-mod/$(uname -r)/64/dm-mod.ko
|
||||
|
||||
|
||||
ventoy_udev_disk_common_hook "${vtdiskname#/dev/}2" "noreplace"
|
||||
|
||||
PATH=$VTPATH_OLD
|
22
IMG/cpio/ventoy/hook/dragora/ventoy-hook.sh
Normal file
@@ -0,0 +1,22 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. $VTOY_PATH/hook/ventoy-os-lib.sh
|
||||
|
||||
$SED "/iso9660/i $BUSYBOX_PATH/sh $VTOY_PATH/hook/dragora/disk_hook.sh" -i /init
|
48
IMG/cpio/ventoy/hook/hyperbola/ventoy-disk.sh
Normal file
@@ -0,0 +1,48 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. /ventoy/hook/ventoy-hook-lib.sh
|
||||
|
||||
vtlog "######### $0 $* ############"
|
||||
|
||||
if is_ventoy_hook_finished; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
wait_for_usb_disk_ready
|
||||
|
||||
vtdiskname=$(get_ventoy_disk_name)
|
||||
if [ "$vtdiskname" = "unknown" ]; then
|
||||
vtlog "ventoy disk not found"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
ventoy_udev_disk_common_hook "${vtdiskname#/dev/}2" "noreplace"
|
||||
|
||||
if [ -n "$1" ]; then
|
||||
blkdev_num=$($VTOY_PATH/tool/dmsetup ls | grep ventoy | sed 's/.*(\([0-9][0-9]*\),.*\([0-9][0-9]*\).*/\1:\2/')
|
||||
vtDM=$(ventoy_find_dm_id ${blkdev_num})
|
||||
|
||||
vtlog "ln -s /dev/$vtDM $1"
|
||||
ln -s /dev/$vtDM "$1"
|
||||
fi
|
||||
|
||||
# OK finish
|
||||
set_ventoy_hook_finish
|
||||
|
44
IMG/cpio/ventoy/hook/hyperbola/ventoy-hook.sh
Normal file
@@ -0,0 +1,44 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. $VTOY_PATH/hook/ventoy-os-lib.sh
|
||||
|
||||
if $GREP -q '^"$mount_handler"' /init; then
|
||||
echo 'use mount_handler ...' >> $VTLOG
|
||||
$SED "/^\"\$mount_handler\"/i\ $BUSYBOX_PATH/sh $VTOY_PATH/hook/hyperbola/ventoy-disk.sh \"\$hyperisodevice\"" -i /init
|
||||
|
||||
if [ -f /hooks/parabolaiso ]; then
|
||||
$SED '/while ! poll_device "${dev}"/a\ if /ventoy/busybox/sh /ventoy/hook/hyperbola/ventoy-timeout.sh ${dev}; then break; fi' -i /hooks/hyperiso
|
||||
fi
|
||||
|
||||
else
|
||||
# some archlinux initramfs doesn't contain device-mapper udev rules file
|
||||
ARCH_UDEV_DIR=$(ventoy_get_udev_conf_dir)
|
||||
if [ -s "$ARCH_UDEV_DIR/13-dm-disk.rules" ]; then
|
||||
echo 'dm-disk rule exist' >> $VTLOG
|
||||
else
|
||||
echo 'Copy dm-disk rule file' >> $VTLOG
|
||||
$CAT $VTOY_PATH/hook/default/13-dm-disk.rules > "$ARCH_UDEV_DIR/13-dm-disk.rules"
|
||||
fi
|
||||
|
||||
# use default proc
|
||||
ventoy_systemd_udevd_work_around
|
||||
|
||||
ventoy_add_udev_rule "$VTOY_PATH/hook/default/udev_disk_hook.sh %k"
|
||||
fi
|
36
IMG/cpio/ventoy/hook/hyperbola/ventoy-timeout.sh
Normal file
@@ -0,0 +1,36 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. /ventoy/hook/ventoy-hook-lib.sh
|
||||
|
||||
vtlog "######### $0 $* ############"
|
||||
|
||||
blkdev_num=$($VTOY_PATH/tool/dmsetup ls | grep ventoy | sed 's/.*(\([0-9][0-9]*\),.*\([0-9][0-9]*\).*/\1:\2/')
|
||||
vtDM=$(ventoy_find_dm_id ${blkdev_num})
|
||||
|
||||
if [ -b /dev/$vtDM ]; then
|
||||
vtlog "ln -s /dev/$vtDM $1"
|
||||
ln -s /dev/$vtDM "$1"
|
||||
exit 0
|
||||
else
|
||||
vtlog "Device-mapper not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
27
IMG/cpio/ventoy/hook/lunar/ventoy-hook.sh
Normal file
@@ -0,0 +1,27 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. $VTOY_PATH/hook/ventoy-os-lib.sh
|
||||
|
||||
$SED "s#printf\(.*\)\$CMDLINE#printf\1\$CMDLINE root=/dev/dm-0#" -i /lib/dracut-lib.sh
|
||||
|
||||
$BUSYBOX_PATH/rm -f /usr/lib/systemd/system-generators/systemd-fstab-generator /lib/systemd/system-generators/systemd-fstab-generator
|
||||
|
||||
ventoy_set_inotify_script lunar/ventoy-inotifyd-hook.sh
|
||||
$BUSYBOX_PATH/cp -a $VTOY_PATH/hook/lunar/ventoy-inotifyd-start.sh /lib/dracut/hooks/pre-udev/01-ventoy-inotifyd-start.sh
|
45
IMG/cpio/ventoy/hook/lunar/ventoy-inotifyd-hook.sh
Normal file
@@ -0,0 +1,45 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. /ventoy/hook/ventoy-hook-lib.sh
|
||||
|
||||
if is_ventoy_hook_finished; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
VTPATH_OLD=$PATH; PATH=$BUSYBOX_PATH:$VTOY_PATH/tool:$PATH
|
||||
|
||||
if is_inotify_ventoy_part $3; then
|
||||
|
||||
vtlog "##### INOTIFYD: $2/$3 is created (YES) ..."
|
||||
|
||||
vtlog "find ventoy partition ..."
|
||||
$BUSYBOX_PATH/sh $VTOY_PATH/hook/default/udev_disk_hook.sh $3 noreplace
|
||||
|
||||
blkdev_num=$($VTOY_PATH/tool/dmsetup ls | grep ventoy | sed 's/.*(\([0-9][0-9]*\),.*\([0-9][0-9]*\).*/\1:\2/')
|
||||
vtDM=$(ventoy_find_dm_id ${blkdev_num})
|
||||
|
||||
mount -t iso9660 /dev/$vtDM /sysroot
|
||||
|
||||
set_ventoy_hook_finish
|
||||
else
|
||||
vtlog "##### INOTIFYD: $2/$3 is created (NO) ..."
|
||||
fi
|
||||
|
||||
PATH=$VTPATH_OLD
|
31
IMG/cpio/ventoy/hook/lunar/ventoy-inotifyd-start.sh
Normal file
@@ -0,0 +1,31 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. /ventoy/hook/ventoy-hook-lib.sh
|
||||
|
||||
vtHook=$($CAT $VTOY_PATH/inotifyd-hook-script.txt)
|
||||
|
||||
vtdisk=$(get_ventoy_disk_name)
|
||||
if [ "$vtdisk" = "unknown" ]; then
|
||||
vtlog "... start inotifyd listen $vtHook ..."
|
||||
$BUSYBOX_PATH/nohup $VTOY_PATH/tool/inotifyd $vtHook /dev:n 2>&- &
|
||||
else
|
||||
vtlog "... $vtdisk already exist ..."
|
||||
$BUSYBOX_PATH/sh $vtHook n /dev "${vtdisk#/dev/}2"
|
||||
fi
|
66
IMG/cpio/ventoy/hook/manjaro/ventoy-disk.sh
Normal file
@@ -0,0 +1,66 @@
|
||||
#!/ventoy/busybox/sh
|
||||
#************************************************************************************
|
||||
# Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#************************************************************************************
|
||||
|
||||
. /ventoy/hook/ventoy-hook-lib.sh
|
||||
|
||||
vtlog "######### $0 $* ############"
|
||||
|
||||
if is_ventoy_hook_finished; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
wait_for_usb_disk_ready
|
||||
|
||||
vtdiskname=$(get_ventoy_disk_name)
|
||||
if [ "$vtdiskname" = "unknown" ]; then
|
||||
vtlog "ventoy disk not found"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
ventoy_udev_disk_common_hook "${vtdiskname#/dev/}2" "noreplace"
|
||||
|
||||
blkdev_num=$($VTOY_PATH/tool/dmsetup ls | grep ventoy | sed 's/.*(\([0-9][0-9]*\),.*\([0-9][0-9]*\).*/\1:\2/')
|
||||
vtDM=$(ventoy_find_dm_id ${blkdev_num})
|
||||
vtlog "blkdev_num=$blkdev_num vtDM=$vtDM ..."
|
||||
|
||||
while [ -n "Y" ]; do
|
||||
if [ -b /dev/$vtDM ]; then
|
||||
break
|
||||
else
|
||||
sleep 0.3
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -n "$1" ]; then
|
||||
vtlog "ln -s /dev/$vtDM $1"
|
||||
ln -s /dev/$vtDM "$1"
|
||||
else
|
||||
vtLABEL=$($BUSYBOX_PATH/blkid /dev/$vtDM | $SED 's/.*LABEL="\([^"]*\)".*/\1/')
|
||||
vtlog "vtLABEL is $vtLABEL"
|
||||
|
||||
if [ -z "$vtLABEL" ]; then
|
||||
vtLABEL=$($SED "s/.*label=\([^ ]*\)/\1/" /proc/cmdline)
|
||||
vtlog "vtLABEL is $vtLABEL from cmdline"
|
||||
fi
|
||||
|
||||
ln -s /dev/$vtDM "/dev/disk/by-label/$vtLABEL"
|
||||
fi
|
||||
|
||||
# OK finish
|
||||
set_ventoy_hook_finish
|
@@ -28,8 +28,22 @@ else
|
||||
$CAT $VTOY_PATH/hook/default/13-dm-disk.rules > "$DISTRO_UDEV_DIR/13-dm-disk.rules"
|
||||
fi
|
||||
|
||||
|
||||
if $GREP -q '^mount_setup$' init; then
|
||||
if $GREP -q '^"$mount_handler"' /init; then
|
||||
echo 'use mount_handler ...' >> $VTLOG
|
||||
|
||||
vthookfile=/hooks/archiso
|
||||
|
||||
if [ -e /hooks/miso ]; then
|
||||
vthookfile=/hooks/miso
|
||||
$SED "/^\"\$mount_handler\"/i\ $BUSYBOX_PATH/sh $VTOY_PATH/hook/manjaro/ventoy-disk.sh \"\$misodevice\"" -i /init
|
||||
else
|
||||
$SED "/^\"\$mount_handler\"/i\ $BUSYBOX_PATH/sh $VTOY_PATH/hook/manjaro/ventoy-disk.sh \"\$archisodevice\"" -i /init
|
||||
fi
|
||||
|
||||
if [ -f $vthookfile ]; then
|
||||
$SED '/while ! poll_device "${dev}"/a\ if /ventoy/busybox/sh /ventoy/hook/manjaro/ventoy-timeout.sh ${dev}; then break; fi' -i $vthookfile
|
||||
fi
|
||||
elif $GREP -q '^mount_setup$' init; then
|
||||
echo "Here use notify ..." >> $VTLOG
|
||||
|
||||
ventoy_set_inotify_script manjaro/ventoy-inotifyd-hook.sh
|
||||
|