Commit 05a1b863 authored by longpanda's avatar longpanda
Browse files

initial commit

parent 2090c6fa
Build a static linked, small dmsetup tool
======== Source Code ========
use an old version of dmsetup
xxx/centos-vault/5.3/os/SRPMS/device-mapper-1.02.28-2.el5.src.rpm
======== Build Envrioment ========
build for 32bit, static linked with dietlibc
1. install centos 6.10 i386 with CentOS-6.10-i386-bin-DVD1.iso
2. yum install gcc kernel-devel package
3. install dietc libc (just make && make install)
4. export PATH=$PATH:/opt/diet/bin
======== Build Step ========
1. extract device mapper source code
2. CC="diet gcc" ./configure --disable-nls --disable-selinux --disable-shared
3. modify include/configure.h file
--- delete the line with "#define malloc rpl_malloc"
--- add 2 defines as follow:
#ifndef UINT32_MAX
#define UINT32_MAX (4294967295U)
#endif
#ifndef UINT64_C
#define UINT64_C(c) c ## ULL
#endif
4. make
5. strip dmsetup/dmsetup
5. get dmsetup/dmsetup as the binary file
File added
========== About Source Code =============
Ventoy add an UEFI application module in MdeModulePkg, so I only put the module's source code here.
You can download the EDK2 code from https://github.com/tianocore/edk2 and merge the code together.
========== Build =============
Follow the EDK2's build instructions
/******************************************************************************
* Ventoy.c
*
* Copyright (c) 2020, longpanda <admin@ventoy.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
*/
#include <Uefi.h>
#include <Library/DebugLib.h>
#include <Library/PrintLib.h>
#include <Library/UefiLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DevicePathLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/UefiApplicationEntryPoint.h>
#include <Protocol/LoadedImage.h>
#include <Guid/FileInfo.h>
#include <Guid/FileSystemInfo.h>
#include <Protocol/BlockIo.h>
#include <Protocol/SimpleFileSystem.h>
#include <Ventoy.h>
BOOLEAN gDebugPrint = FALSE;
BOOLEAN gLoadIsoEfi = FALSE;
ventoy_chain_head *g_chain;
ventoy_img_chunk *g_chunk;
UINT32 g_img_chunk_num;
ventoy_override_chunk *g_override_chunk;
UINT32 g_override_chunk_num;
ventoy_virt_chunk *g_virt_chunk;
UINT32 g_virt_chunk_num;
vtoy_block_data gBlockData;
ventoy_sector_flag *g_sector_flag = NULL;
UINT32 g_sector_flag_num = 0;
static grub_env_get_pf grub_env_get = NULL;
CONST CHAR16 gIso9660EfiDriverPath[] = ISO9660_EFI_DRIVER_PATH;
/* Boot filename */
CONST CHAR16 *gEfiBootFileName[] =
{
EFI_REMOVABLE_MEDIA_FILE_NAME,
L"\\EFI\\BOOT\\GRUBX64.EFI",
L"\\EFI\\BOOT\\BOOTx64.EFI",
L"\\EFI\\BOOT\\bootx64.efi",
};
/* EFI block device vendor device path GUID */
EFI_GUID gVtoyBlockDevicePathGuid = VTOY_BLOCK_DEVICE_PATH_GUID;
VOID EFIAPI VtoyDebug(IN CONST CHAR8 *Format, ...)
{
VA_LIST Marker;
CHAR16 Buffer[512];
VA_START (Marker, Format);
UnicodeVSPrintAsciiFormat(Buffer, sizeof(Buffer), Format, Marker);
VA_END (Marker);
gST->ConOut->OutputString(gST->ConOut, Buffer);
}
VOID EFIAPI ventoy_clear_input(VOID)
{
EFI_INPUT_KEY Key;
gST->ConIn->Reset(gST->ConIn, FALSE);
while (EFI_SUCCESS == gST->ConIn->ReadKeyStroke(gST->ConIn, &Key))
{
;
}
gST->ConIn->Reset(gST->ConIn, FALSE);
}
static void EFIAPI ventoy_dump_img_chunk(ventoy_chain_head *chain)
{
UINT32 i;
int errcnt = 0;
UINT64 img_sec = 0;
ventoy_img_chunk *chunk;
chunk = (ventoy_img_chunk *)((char *)chain + chain->img_chunk_offset);
debug("##################### ventoy_dump_img_chunk #######################");
for (i = 0; i < chain->img_chunk_num; i++)
{
debug("%2u: [ %u - %u ] <==> [ %llu - %llu ]",
i, chunk[i].img_start_sector, chunk[i].img_end_sector,
chunk[i].disk_start_sector, chunk[i].disk_end_sector);
if (i > 0 && (chunk[i].img_start_sector != chunk[i - 1].img_end_sector + 1))
{
errcnt++;
}
img_sec += chunk[i].img_end_sector - chunk[i].img_start_sector + 1;
}
if (errcnt == 0 && (img_sec * 2048 == g_chain->real_img_size_in_bytes))
{
debug("image chunk size check success");
}
else
{
debug("image chunk size check failed %d", errcnt);
}
ventoy_debug_pause();
}
static void EFIAPI ventoy_dump_override_chunk(ventoy_chain_head *chain)
{
UINT32 i;
ventoy_override_chunk *chunk;
chunk = (ventoy_override_chunk *)((char *)chain + chain->override_chunk_offset);
debug("##################### ventoy_dump_override_chunk #######################");
for (i = 0; i < g_override_chunk_num; i++)
{
debug("%2u: [ %llu, %u ]", i, chunk[i].img_offset, chunk[i].override_size);
}
ventoy_debug_pause();
}
static void EFIAPI ventoy_dump_virt_chunk(ventoy_chain_head *chain)
{
UINT32 i;
ventoy_virt_chunk *node;
debug("##################### ventoy_dump_virt_chunk #######################");
debug("virt_chunk_offset=%u", chain->virt_chunk_offset);
debug("virt_chunk_num=%u", chain->virt_chunk_num);
node = (ventoy_virt_chunk *)((char *)chain + chain->virt_chunk_offset);
for (i = 0; i < chain->virt_chunk_num; i++, node++)
{
debug("%2u: mem:[ %u, %u, %u ] remap:[ %u, %u, %u ]", i,
node->mem_sector_start,
node->mem_sector_end,
node->mem_sector_offset,
node->remap_sector_start,
node->remap_sector_end,
node->org_sector_start);
}
ventoy_debug_pause();
}
static void EFIAPI ventoy_dump_chain(ventoy_chain_head *chain)
{
UINT32 i = 0;
UINT8 chksum = 0;
UINT8 *guid;
guid = chain->os_param.vtoy_disk_guid;
for (i = 0; i < sizeof(ventoy_os_param); i++)
{
chksum += *((UINT8 *)(&(chain->os_param)) + i);
}
debug("##################### ventoy_dump_chain #######################");
debug("os_param->chksum=0x%x (%a)", chain->os_param.chksum, chksum ? "FAILED" : "SUCCESS");
debug("os_param->vtoy_disk_guid=%02x%02x%02x%02x", guid[0], guid[1], guid[2], guid[3]);
debug("os_param->vtoy_disk_size=%llu", chain->os_param.vtoy_disk_size);
debug("os_param->vtoy_disk_part_id=%u", chain->os_param.vtoy_disk_part_id);
debug("os_param->vtoy_disk_part_type=%u", chain->os_param.vtoy_disk_part_type);
debug("os_param->vtoy_img_path=<%a>", chain->os_param.vtoy_img_path);
debug("os_param->vtoy_img_size=<%llu>", chain->os_param.vtoy_img_size);
debug("os_param->vtoy_img_location_addr=<0x%llx>", chain->os_param.vtoy_img_location_addr);
debug("os_param->vtoy_img_location_len=<%u>", chain->os_param.vtoy_img_location_len);
ventoy_debug_pause();
debug("chain->disk_drive=0x%x", chain->disk_drive);
debug("chain->disk_sector_size=%u", chain->disk_sector_size);
debug("chain->real_img_size_in_bytes=%llu", chain->real_img_size_in_bytes);
debug("chain->virt_img_size_in_bytes=%llu", chain->virt_img_size_in_bytes);
debug("chain->boot_catalog=%u", chain->boot_catalog);
debug("chain->img_chunk_offset=%u", chain->img_chunk_offset);
debug("chain->img_chunk_num=%u", chain->img_chunk_num);
debug("chain->override_chunk_offset=%u", chain->override_chunk_offset);
debug("chain->override_chunk_num=%u", chain->override_chunk_num);
ventoy_debug_pause();
ventoy_dump_img_chunk(chain);
ventoy_dump_override_chunk(chain);
ventoy_dump_virt_chunk(chain);
}
EFI_HANDLE EFIAPI ventoy_get_parent_handle(IN EFI_DEVICE_PATH_PROTOCOL *pDevPath)
{
EFI_HANDLE Handle = NULL;
EFI_STATUS Status = EFI_SUCCESS;
EFI_DEVICE_PATH_PROTOCOL *pLastNode = NULL;
EFI_DEVICE_PATH_PROTOCOL *pCurNode = NULL;
EFI_DEVICE_PATH_PROTOCOL *pTmpDevPath = NULL;
pTmpDevPath = DuplicateDevicePath(pDevPath);
if (!pTmpDevPath)
{
return NULL;
}
pCurNode = pTmpDevPath;
while (!IsDevicePathEnd(pCurNode))
{
pLastNode = pCurNode;
pCurNode = NextDevicePathNode(pCurNode);
}
if (pLastNode)
{
CopyMem(pLastNode, pCurNode, sizeof(EFI_DEVICE_PATH_PROTOCOL));
}
pCurNode = pTmpDevPath;
Status = gBS->LocateDevicePath(&gEfiDevicePathProtocolGuid, &pCurNode, &Handle);
debug("Status:%r Parent Handle:%p DP:%s", Status, Handle, ConvertDevicePathToText(pTmpDevPath, FALSE, FALSE));
FreePool(pTmpDevPath);
return Handle;
}
EFI_STATUS EFIAPI ventoy_block_io_reset
(
IN EFI_BLOCK_IO_PROTOCOL *This,
IN BOOLEAN ExtendedVerification
)
{
(VOID)This;
(VOID)ExtendedVerification;
return EFI_SUCCESS;
}
STATIC EFI_STATUS EFIAPI ventoy_read_iso_sector
(
IN UINT64 Sector,
IN UINTN Count,
OUT VOID *Buffer
)
{
EFI_STATUS Status = EFI_SUCCESS;
EFI_LBA MapLba = 0;
UINT32 i = 0;
UINTN secLeft = 0;
UINTN secRead = 0;
UINT64 ReadStart = 0;
UINT64 ReadEnd = 0;
UINT64 OverrideStart = 0;
UINT64 OverrideEnd= 0;
UINT8 *pCurBuf = (UINT8 *)Buffer;
ventoy_img_chunk *pchunk = g_chunk;
ventoy_override_chunk *pOverride = g_override_chunk;
EFI_BLOCK_IO_PROTOCOL *pRawBlockIo = gBlockData.pRawBlockIo;
debug("read iso sector %lu count %u", Sector, Count);
ReadStart = Sector * 2048;
ReadEnd = (Sector + Count) * 2048;
for (i = 0; Count > 0 && i < g_img_chunk_num; i++, pchunk++)
{
if (Sector >= pchunk->img_start_sector && Sector <= pchunk->img_end_sector)
{
if (g_chain->disk_sector_size == 512)
{
MapLba = (Sector - pchunk->img_start_sector) * 4 + pchunk->disk_start_sector;
}
else
{
MapLba = (Sector - pchunk->img_start_sector) * 2048 / g_chain->disk_sector_size + pchunk->disk_start_sector;
}
secLeft = pchunk->img_end_sector + 1 - Sector;
secRead = (Count < secLeft) ? Count : secLeft;
Status = pRawBlockIo->ReadBlocks(pRawBlockIo, pRawBlockIo->Media->MediaId,
MapLba, secRead * 2048, pCurBuf);
if (EFI_ERROR(Status))
{
debug("Raw disk read block failed %r", Status);
return Status;
}
Count -= secRead;
Sector += secRead;
pCurBuf += secRead * 2048;
}
}
if (ReadStart > g_chain->real_img_size_in_bytes)
{
return EFI_SUCCESS;
}
/* override data */
pCurBuf = (UINT8 *)Buffer;
for (i = 0; i < g_override_chunk_num; i++, pOverride++)
{
OverrideStart = pOverride->img_offset;
OverrideEnd = pOverride->img_offset + pOverride->override_size;
if (OverrideStart >= ReadEnd || ReadStart >= OverrideEnd)
{
continue;
}
if (ReadStart <= OverrideStart)
{
if (ReadEnd <= OverrideEnd)
{
CopyMem(pCurBuf + OverrideStart - ReadStart, pOverride->override_data, ReadEnd - OverrideStart);
}
else
{
CopyMem(pCurBuf + OverrideStart - ReadStart, pOverride->override_data, pOverride->override_size);
}
}
else
{
if (ReadEnd <= OverrideEnd)
{
CopyMem(pCurBuf, pOverride->override_data + ReadStart - OverrideStart, ReadEnd - ReadStart);
}
else
{
CopyMem(pCurBuf, pOverride->override_data + ReadStart - OverrideStart, OverrideEnd - ReadStart);
}
}
}
return EFI_SUCCESS;
}
EFI_STATUS EFIAPI ventoy_block_io_read
(
IN EFI_BLOCK_IO_PROTOCOL *This,
IN UINT32 MediaId,
IN EFI_LBA Lba,
IN UINTN BufferSize,
OUT VOID *Buffer
)
{
UINT32 i = 0;
UINT32 j = 0;
UINT32 lbacount = 0;
UINT32 secNum = 0;
UINT64 offset = 0;
EFI_LBA curlba = 0;
EFI_LBA lastlba = 0;
UINT8 *lastbuffer;
ventoy_sector_flag *cur_flag;
ventoy_virt_chunk *node;
//debug("### ventoy_block_io_read sector:%u count:%u", (UINT32)Lba, (UINT32)BufferSize / 2048);
secNum = BufferSize / 2048;
offset = Lba * 2048;
if (offset + BufferSize < g_chain->real_img_size_in_bytes)
{
return ventoy_read_iso_sector(Lba, secNum, Buffer);
}
if (secNum > g_sector_flag_num)
{
cur_flag = AllocatePool(secNum * sizeof(ventoy_sector_flag));
if (NULL == cur_flag)
{
return EFI_OUT_OF_RESOURCES;
}
FreePool(g_sector_flag);
g_sector_flag = cur_flag;
g_sector_flag_num = secNum;
}
for (curlba = Lba, cur_flag = g_sector_flag, j = 0; j < secNum; j++, curlba++, cur_flag++)
{
cur_flag->flag = 0;
for (node = g_virt_chunk, i = 0; i < g_virt_chunk_num; i++, node++)
{
if (curlba >= node->mem_sector_start && curlba < node->mem_sector_end)
{
CopyMem((UINT8 *)Buffer + j * 2048,
(char *)g_virt_chunk + node->mem_sector_offset + (curlba - node->mem_sector_start) * 2048,
2048);
cur_flag->flag = 1;
break;
}
else if (curlba >= node->remap_sector_start && curlba < node->remap_sector_end)
{
cur_flag->remap_lba = node->org_sector_start + curlba - node->remap_sector_start;
cur_flag->flag = 2;
break;
}
}
}
for (curlba = Lba, cur_flag = g_sector_flag, j = 0; j < secNum; j++, curlba++, cur_flag++)
{
if (cur_flag->flag == 2)
{
if (lastlba == 0)
{
lastbuffer = (UINT8 *)Buffer + j * 2048;
lastlba = cur_flag->remap_lba;
lbacount = 1;
}
else if (lastlba + lbacount == cur_flag->remap_lba)
{
lbacount++;
}
else
{
ventoy_read_iso_sector(lastlba, lbacount, lastbuffer);
lastbuffer = (UINT8 *)Buffer + j * 2048;
lastlba = cur_flag->remap_lba;
lbacount = 1;
}
}
}
if (lbacount > 0)
{
ventoy_read_iso_sector(lastlba, lbacount, lastbuffer);
}
return EFI_SUCCESS;
}
EFI_STATUS EFIAPI ventoy_block_io_write
(
IN EFI_BLOCK_IO_PROTOCOL *This,
IN UINT32 MediaId,
IN EFI_LBA Lba,
IN UINTN BufferSize,
IN VOID *Buffer
)
{
(VOID)This;
(VOID)MediaId;
(VOID)Lba;
(VOID)BufferSize;
(VOID)Buffer;
return EFI_WRITE_PROTECTED;
}
EFI_STATUS EFIAPI ventoy_block_io_flush(IN EFI_BLOCK_IO_PROTOCOL *This)
{
(VOID)This;
return EFI_SUCCESS;
}
EFI_STATUS EFIAPI ventoy_fill_device_path(VOID)
{
UINTN NameLen = 0;
UINT8 TmpBuf[128] = {0};
VENDOR_DEVICE_PATH *venPath = NULL;
venPath = (VENDOR_DEVICE_PATH *)TmpBuf;
NameLen = StrSize(VTOY_BLOCK_DEVICE_PATH_NAME);
venPath->Header.Type = HARDWARE_DEVICE_PATH;
venPath->Header.SubType = HW_VENDOR_DP;
venPath->Header.Length[0] = sizeof(VENDOR_DEVICE_PATH) + NameLen;
venPath->Header.Length[1] = 0;
CopyMem(&venPath->Guid, &gVtoyBlockDevicePathGuid, sizeof(EFI_GUID));
CopyMem(venPath + 1, VTOY_BLOCK_DEVICE_PATH_NAME, NameLen);
gBlockData.Path = AppendDevicePathNode(NULL, (EFI_DEVICE_PATH_PROTOCOL *)TmpBuf);
gBlockData.DevicePathCompareLen = sizeof(VENDOR_DEVICE_PATH) + NameLen;
debug("gBlockData.Path=<%s>\n", ConvertDevicePathToText(gBlockData.Path, FALSE, FALSE));
return EFI_SUCCESS;
}
EFI_STATUS EFIAPI ventoy_set_variable(VOID)
{
EFI_STATUS Status = EFI_SUCCESS;
EFI_GUID VarGuid = VENTOY_GUID;
Status = gRT->SetVariable(L"VentoyOsParam", &VarGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
sizeof(g_chain->os_param), &(g_chain->os_param));
debug("set efi variable %r", Status);
return Status;
}
EFI_STATUS EFIAPI ventoy_delete_variable(VOID)
{
EFI_STATUS Status = EFI_SUCCESS;
EFI_GUID VarGuid = VENTOY_GUID;
Status = gRT->SetVariable(L"VentoyOsParam", &VarGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
0, NULL);
debug("delete efi variable %r", Status);
return Status;
}
EFI_STATUS EFIAPI ventoy_install_blockio(IN EFI_HANDLE ImageHandle)
{
EFI_STATUS Status = EFI_SUCCESS;
EFI_BLOCK_IO_PROTOCOL *pBlockIo = &(gBlockData.BlockIo);
ventoy_fill_device_path();
gBlockData.Media.BlockSize = 2048;
gBlockData.Media.LastBlock = g_chain->virt_img_size_in_bytes / 2048 - 1;
gBlockData.Media.ReadOnly = TRUE;
gBlockData.Media.MediaPresent = 1;
gBlockData.Media.LogicalBlocksPerPhysicalBlock = 1;
pBlockIo->Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3;
pBlockIo->Media = &(gBlockData.Media);
pBlockIo->Reset = ventoy_block_io_reset;
pBlockIo->ReadBlocks = ventoy_block_io_read;
pBlockIo->WriteBlocks = ventoy_block_io_write;
pBlockIo->FlushBlocks = ventoy_block_io_flush;
Status = gBS->InstallMultipleProtocolInterfaces(&gBlockData.Handle,
&gEfiBlockIoProtocolGuid, &gBlockData.BlockIo,
&gEfiDevicePathProtocolGuid, gBlockData.Path,
NULL);
debug("Install protocol %r", Status);
if (EFI_ERROR(Status))
{
return Status;
}
Status = gBS->ConnectController(gBlockData.Handle, NULL, NULL, 1);
debug("Connect controller %r", Status);
return EFI_SUCCESS;
}
EFI_STATUS EFIAPI ventoy_load_image
(
IN EFI_HANDLE ImageHandle,
IN EFI_DEVICE_PATH_PROTOCOL *pDevicePath,
IN CONST CHAR16 *FileName,
IN UINTN FileNameLen,
OUT EFI_HANDLE *Image
)
{
EFI_STATUS Status = EFI_SUCCESS;
CHAR16 TmpBuf[256] = {0};
FILEPATH_DEVICE_PATH *pFilePath = NULL;
EFI_DEVICE_PATH_PROTOCOL *pImgPath = NULL;
pFilePath = (FILEPATH_DEVICE_PATH *)TmpBuf;
pFilePath->Header.Type = MEDIA_DEVICE_PATH;
pFilePath->Header.SubType = MEDIA_FILEPATH_DP;
pFilePath->Header.Length[0] = FileNameLen + sizeof(EFI_DEVICE_PATH_PROTOCOL);
pFilePath->Header.Length[1] = 0;
CopyMem(pFilePath->PathName, FileName, FileNameLen);
pImgPath = AppendDevicePathNode(pDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)pFilePath);
if (!pImgPath)
{
return EFI_NOT_FOUND;
}
Status = gBS->LoadImage(FALSE, ImageHandle, pImgPath, NULL, 0, Image);
debug("Load Image File %r DP: <%s>", Status, ConvertDevicePathToText(pImgPath, FALSE, FALSE));
FreePool(pImgPath);
return Status;
}
STATIC EFI_STATUS EFIAPI ventoy_find_iso_disk(IN EFI_HANDLE ImageHandle)
{
UINTN i = 0;
UINTN Count = 0;
UINT64 DiskSize = 0;
UINT8 *pBuffer = NULL;
EFI_HANDLE *Handles;
EFI_STATUS Status = EFI_SUCCESS;
EFI_BLOCK_IO_PROTOCOL *pBlockIo;
pBuffer = AllocatePool(2048);
if (!pBuffer)
{
return EFI_OUT_OF_RESOURCES;
}
Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiBlockIoProtocolGuid,
NULL, &Count, &Handles);
if (EFI_ERROR(Status))
{
FreePool(pBuffer);
return Status;
}
for (i = 0; i < Count; i++)
{
Status = gBS->HandleProtocol(Handles[i], &gEfiBlockIoProtocolGuid, (VOID **)&pBlockIo);
if (EFI_ERROR(Status))
{
continue;
}
DiskSize = (pBlockIo->Media->LastBlock + 1) * pBlockIo->Media->BlockSize;
debug("This Disk size: %llu", DiskSize);
if (g_chain->os_param.vtoy_disk_size != DiskSize)
{
continue;
}
Status = pBlockIo->ReadBlocks(pBlockIo, pBlockIo->Media->MediaId, 0, 512, pBuffer);
if (EFI_ERROR(Status))
{
debug("ReadBlocks filed %r", Status);
continue;
}
if (CompareMem(g_chain->os_param.vtoy_disk_guid, pBuffer + 0x180, 16) == 0)
{
gBlockData.RawBlockIoHandle = Handles[i];
gBlockData.pRawBlockIo = pBlockIo;
gBS->OpenProtocol(Handles[i], &gEfiDevicePathProtocolGuid,
(VOID **)&(gBlockData.pDiskDevPath),
ImageHandle,
Handles[i],
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
debug("Find Ventoy Disk Handle:%p DP:%s", Handles[i],
ConvertDevicePathToText(gBlockData.pDiskDevPath, FALSE, FALSE));
break;
}
}
FreePool(Handles);
if (i >= Count)
{
return EFI_NOT_FOUND;
}
else
{
return EFI_SUCCESS;
}
}
STATIC EFI_STATUS EFIAPI ventoy_find_iso_disk_fs(IN EFI_HANDLE ImageHandle)
{
UINTN i = 0;
UINTN Count = 0;
EFI_HANDLE Parent = NULL;
EFI_HANDLE *Handles = NULL;
EFI_STATUS Status = EFI_SUCCESS;
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *pFile = NULL;
EFI_DEVICE_PATH_PROTOCOL *pDevPath = NULL;
Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiSimpleFileSystemProtocolGuid,
NULL, &Count, &Handles);
if (EFI_ERROR(Status))
{
return Status;
}
debug("ventoy_find_iso_disk_fs fs count:%u", Count);
for (i = 0; i < Count; i++)
{
Status = gBS->HandleProtocol(Handles[i], &gEfiSimpleFileSystemProtocolGuid, (VOID **)&pFile);
if (EFI_ERROR(Status))
{
continue;
}
Status = gBS->OpenProtocol(Handles[i], &gEfiDevicePathProtocolGuid,
(VOID **)&pDevPath,
ImageHandle,
Handles[i],
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (EFI_ERROR(Status))
{
debug("Failed to open device path protocol %r", Status);
continue;
}
debug("Handle:%p FS DP: <%s>", Handles[i], ConvertDevicePathToText(pDevPath, FALSE, FALSE));
Parent = ventoy_get_parent_handle(pDevPath);
if (Parent == gBlockData.RawBlockIoHandle)
{
debug("Find ventoy disk fs");
gBlockData.DiskFsHandle = Handles[i];
gBlockData.pDiskFs = pFile;
gBlockData.pDiskFsDevPath = pDevPath;
break;
}
}
FreePool(Handles);
return EFI_SUCCESS;
}
STATIC EFI_STATUS EFIAPI ventoy_load_isoefi_driver(IN EFI_HANDLE ImageHandle)
{
EFI_HANDLE Image = NULL;
EFI_STATUS Status = EFI_SUCCESS;
CHAR16 LogVar[4] = L"5";
Status = ventoy_load_image(ImageHandle, gBlockData.pDiskFsDevPath,
gIso9660EfiDriverPath,
sizeof(gIso9660EfiDriverPath),
&Image);
debug("load iso efi driver status:%r", Status);
if (gDebugPrint)
{
gRT->SetVariable(L"FS_LOGGING", &gShellVariableGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
sizeof(LogVar), LogVar);
}
gRT->SetVariable(L"FS_NAME_NOCASE", &gShellVariableGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
sizeof(LogVar), LogVar);
gBlockData.IsoDriverImage = Image;
Status = gBS->StartImage(Image, NULL, NULL);
debug("Start iso efi driver status:%r", Status);
return EFI_SUCCESS;
}
static int ventoy_update_image_location(ventoy_os_param *param)
{
EFI_STATUS Status = EFI_SUCCESS;
UINT8 chksum = 0;
unsigned int i;
unsigned int length;
UINTN address = 0;
void *buffer = NULL;
ventoy_image_location *location = NULL;
ventoy_image_disk_region *region = NULL;
ventoy_img_chunk *chunk = g_chunk;
length = sizeof(ventoy_image_location) + (g_img_chunk_num - 1) * sizeof(ventoy_image_disk_region);
Status = gBS->AllocatePool(EfiRuntimeServicesData, length + 4096 * 2, &buffer);
if (EFI_ERROR(Status) || NULL == buffer)
{
debug("Failed to allocate runtime pool %r\n", Status);
return 1;
}
address = (UINTN)buffer;
if (address % 4096)
{
address += 4096 - (address % 4096);
}
param->chksum = 0;
param->vtoy_img_location_addr = address;
param->vtoy_img_location_len = length;
/* update check sum */
for (i = 0; i < sizeof(ventoy_os_param); i++)
{
chksum += *((UINT8 *)param + i);
}
param->chksum = (chksum == 0) ? 0 : (UINT8)(0x100 - chksum);
location = (ventoy_image_location *)(unsigned long)(param->vtoy_img_location_addr);
if (NULL == location)
{
return 0;
}
CopyMem(&location->guid, &param->guid, sizeof(ventoy_guid));
location->image_sector_size = 2048;
location->disk_sector_size = g_chain->disk_sector_size;
location->region_count = g_img_chunk_num;
region = location->regions;
for (i = 0; i < g_img_chunk_num; i++)
{
region->image_sector_count = chunk->img_end_sector - chunk->img_start_sector + 1;
region->image_start_sector = chunk->img_start_sector;
region->disk_start_sector = chunk->disk_start_sector;
region++;
chunk++;
}
return 0;
}
STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
{
UINT32 i = 0;
UINT8 chksum = 0;
CHAR16 *pPos = NULL;
CHAR16 *pCmdLine = NULL;
EFI_STATUS Status = EFI_SUCCESS;
ventoy_grub_param *pGrubParam = NULL;
EFI_LOADED_IMAGE_PROTOCOL *pImageInfo = NULL;
Status = gBS->HandleProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&pImageInfo);
if (EFI_ERROR(Status))
{
VtoyDebug("Failed to handle load image protocol %r", Status);
return Status;
}
pCmdLine = (CHAR16 *)AllocatePool(pImageInfo->LoadOptionsSize + 4);
SetMem(pCmdLine, pImageInfo->LoadOptionsSize + 4, 0);
CopyMem(pCmdLine, pImageInfo->LoadOptions, pImageInfo->LoadOptionsSize);
if (StrStr(pCmdLine, L"debug"))
{
gDebugPrint = TRUE;
}
if (StrStr(pCmdLine, L"isoefi=on"))
{
gLoadIsoEfi = TRUE;
}
debug("cmdline:<%s>", pCmdLine);
pPos = StrStr(pCmdLine, L"env_param=");
if (!pPos)
{
return EFI_INVALID_PARAMETER;
}
pGrubParam = (ventoy_grub_param *)StrHexToUintn(pPos + StrLen(L"env_param="));
grub_env_get = pGrubParam->grub_env_get;
pPos = StrStr(pCmdLine, L"mem:");
g_chain = (ventoy_chain_head *)StrHexToUintn(pPos + 4);
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);
g_override_chunk_num = g_chain->override_chunk_num;
g_virt_chunk = (ventoy_virt_chunk *)((char *)g_chain + g_chain->virt_chunk_offset);
g_virt_chunk_num = g_chain->virt_chunk_num;
for (i = 0; i < sizeof(ventoy_os_param); i++)
{
chksum += *((UINT8 *)(&(g_chain->os_param)) + i);
}
if (gDebugPrint)
{
debug("os param checksum: 0x%x %a", g_chain->os_param.chksum, chksum ? "FAILED" : "SUCCESS");
}
ventoy_update_image_location(&(g_chain->os_param));
if (gDebugPrint)
{
ventoy_dump_chain(g_chain);
}
FreePool(pCmdLine);
return EFI_SUCCESS;
}
EFI_STATUS EFIAPI ventoy_boot(IN EFI_HANDLE ImageHandle)
{
UINTN i = 0;
UINTN j = 0;
UINTN Find = 0;
UINTN Count = 0;
EFI_HANDLE Image = NULL;
EFI_HANDLE *Handles = NULL;
EFI_STATUS Status = EFI_SUCCESS;
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *pFile = NULL;
EFI_DEVICE_PATH_PROTOCOL *pDevPath = NULL;
Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiSimpleFileSystemProtocolGuid,
NULL, &Count, &Handles);
if (EFI_ERROR(Status))
{
return Status;
}
debug("ventoy_boot fs count:%u", Count);
for (i = 0; i < Count; i++)
{
Status = gBS->HandleProtocol(Handles[i], &gEfiSimpleFileSystemProtocolGuid, (VOID **)&pFile);
if (EFI_ERROR(Status))
{
continue;
}
Status = gBS->OpenProtocol(Handles[i], &gEfiDevicePathProtocolGuid,
(VOID **)&pDevPath,
ImageHandle,
Handles[i],
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (EFI_ERROR(Status))
{
debug("Failed to open device path protocol %r", Status);
continue;
}
debug("Handle:%p FS DP: <%s>", Handles[i], ConvertDevicePathToText(pDevPath, FALSE, FALSE));
if (CompareMem(gBlockData.Path, pDevPath, gBlockData.DevicePathCompareLen))
{
debug("Not ventoy disk file system");
continue;
}
for (j = 0; j < ARRAY_SIZE(gEfiBootFileName); j++)
{
Status = ventoy_load_image(ImageHandle, pDevPath, gEfiBootFileName[j],
StrSize(gEfiBootFileName[j]), &Image);
if (EFI_SUCCESS == Status)
{
break;
}
debug("Failed to load image %r <%s>", Status, gEfiBootFileName[j]);
}
if (j >= ARRAY_SIZE(gEfiBootFileName))
{
continue;
}
Find++;
debug("Find boot file, now try to boot .....");
ventoy_debug_pause();
if (gDebugPrint)
{
gST->ConIn->Reset(gST->ConIn, FALSE);
}
Status = gBS->StartImage(Image, NULL, NULL);
if (EFI_ERROR(Status))
{
debug("Failed to start image %r", Status);
gBS->UnloadImage(Image);
break;
}
}
FreePool(Handles);
if (Find == 0)
{
return EFI_NOT_FOUND;
}
return EFI_SUCCESS;
}
EFI_STATUS EFIAPI ventoy_clean_env(VOID)
{
FreePool(g_sector_flag);
g_sector_flag_num = 0;
if (gLoadIsoEfi && gBlockData.IsoDriverImage)
{
gBS->UnloadImage(gBlockData.IsoDriverImage);
}
gBS->DisconnectController(gBlockData.Handle, NULL, NULL);
gBS->UninstallMultipleProtocolInterfaces(gBlockData.Handle,
&gEfiBlockIoProtocolGuid, &gBlockData.BlockIo,
&gEfiDevicePathProtocolGuid, gBlockData.Path,
NULL);
ventoy_delete_variable();
if (g_chain->os_param.vtoy_img_location_addr)
{
FreePool((VOID *)(UINTN)g_chain->os_param.vtoy_img_location_addr);
}
return EFI_SUCCESS;
}
EFI_STATUS EFIAPI VentoyEfiMain
(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status = EFI_SUCCESS;
g_sector_flag_num = 512; /* initial value */
g_sector_flag = AllocatePool(g_sector_flag_num * sizeof(ventoy_sector_flag));
if (NULL == g_sector_flag)
{
return EFI_OUT_OF_RESOURCES;
}
gST->ConOut->ClearScreen(gST->ConOut);
ventoy_clear_input();
ventoy_parse_cmdline(ImageHandle);
ventoy_set_variable();
ventoy_find_iso_disk(ImageHandle);
if (gLoadIsoEfi)
{
ventoy_find_iso_disk_fs(ImageHandle);
ventoy_load_isoefi_driver(ImageHandle);
}
ventoy_debug_pause();
ventoy_install_blockio(ImageHandle);
ventoy_debug_pause();
Status = ventoy_boot(ImageHandle);
if (EFI_NOT_FOUND == Status)
{
gST->ConOut->OutputString(gST->ConOut, L"No bootfile found for UEFI!\r\n");
gST->ConOut->OutputString(gST->ConOut, L"Maybe the image does not support " VENTOY_UEFI_DESC L"!\r\n");
sleep(300);
}
ventoy_clean_env();
ventoy_clear_input();
gST->ConOut->ClearScreen(gST->ConOut);
return EFI_SUCCESS;
}
/******************************************************************************
* Ventoy.h
*
* Copyright (c) 2020, longpanda <admin@ventoy.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef __VENTOY_H__
#define __VENTOY_H__
#define COMPILE_ASSERT(expr) extern char __compile_assert[(expr) ? 1 : -1]
#define VENTOY_GUID { 0x77772020, 0x2e77, 0x6576, { 0x6e, 0x74, 0x6f, 0x79, 0x2e, 0x6e, 0x65, 0x74 }}
#pragma pack(1)
typedef struct ventoy_guid
{
UINT32 data1;
UINT16 data2;
UINT16 data3;
UINT8 data4[8];
}ventoy_guid;
typedef struct ventoy_image_disk_region
{
UINT32 image_sector_count; /* image sectors contained in this region */
UINT32 image_start_sector; /* image sector start */
UINT64 disk_start_sector; /* disk sector start */
}ventoy_image_disk_region;
typedef struct ventoy_image_location
{
ventoy_guid guid;
/* image sector size, currently this value is always 2048 */
UINT32 image_sector_size;
/* disk sector size, normally the value is 512 */
UINT32 disk_sector_size;
UINT32 region_count;
/*
* disk region data
* If the image file has more than one fragments in disk,
* there will be more than one region data here.
*
*/
ventoy_image_disk_region regions[1];
/* ventoy_image_disk_region regions[2~region_count-1] */
}ventoy_image_location;
typedef struct ventoy_os_param
{
ventoy_guid guid; // VENTOY_GUID
UINT8 chksum; // checksum
UINT8 vtoy_disk_guid[16];
UINT64 vtoy_disk_size; // disk size in bytes
UINT16 vtoy_disk_part_id; // begin with 1
UINT16 vtoy_disk_part_type; // 0:exfat 1:ntfs other: reserved
char vtoy_img_path[384]; // It seems to be enough, utf-8 format
UINT64 vtoy_img_size; // image file size in bytes
/*
* Ventoy will write a copy of ventoy_image_location data into runtime memory
* this is the physically address and length of that memory.
* Address 0 means no such data exist.
* Address will be aligned by 4KB.
*
*/
UINT64 vtoy_img_location_addr;
UINT32 vtoy_img_location_len;
UINT64 vtoy_reserved[4]; // Internal use by ventoy
UINT8 reserved[31];
}ventoy_os_param;
#pragma pack()
// compile assert to check that size of ventoy_os_param must be 512
COMPILE_ASSERT(sizeof(ventoy_os_param) == 512);
#pragma pack(4)
typedef struct ventoy_chain_head
{
ventoy_os_param os_param;
UINT32 disk_drive;
UINT32 drive_map;
UINT32 disk_sector_size;
UINT64 real_img_size_in_bytes;
UINT64 virt_img_size_in_bytes;
UINT32 boot_catalog;
UINT8 boot_catalog_sector[2048];
UINT32 img_chunk_offset;
UINT32 img_chunk_num;
UINT32 override_chunk_offset;
UINT32 override_chunk_num;
UINT32 virt_chunk_offset;
UINT32 virt_chunk_num;
}ventoy_chain_head;
typedef struct ventoy_img_chunk
{
UINT32 img_start_sector; //2KB
UINT32 img_end_sector;
UINT64 disk_start_sector; // in disk_sector_size
UINT64 disk_end_sector;
}ventoy_img_chunk;
typedef struct ventoy_override_chunk
{
UINT64 img_offset;
UINT32 override_size;
UINT8 override_data[512];
}ventoy_override_chunk;
typedef struct ventoy_virt_chunk
{
UINT32 mem_sector_start;
UINT32 mem_sector_end;
UINT32 mem_sector_offset;
UINT32 remap_sector_start;
UINT32 remap_sector_end;
UINT32 org_sector_start;
}ventoy_virt_chunk;
#pragma pack()
#define VTOY_BLOCK_DEVICE_PATH_GUID \
{ 0x37b87ac6, 0xc180, 0x4583, { 0xa7, 0x05, 0x41, 0x4d, 0xa8, 0xf7, 0x7e, 0xd2 }}
#define VTOY_BLOCK_DEVICE_PATH_NAME L"ventoy"
#if defined (MDE_CPU_IA32)
#define VENTOY_UEFI_DESC L"IA32 UEFI"
#elif defined (MDE_CPU_X64)
#define VENTOY_UEFI_DESC L"X64 UEFI"
#elif defined (MDE_CPU_EBC)
#elif defined (MDE_CPU_ARM)
#define VENTOY_UEFI_DESC L"ARM UEFI"
#elif defined (MDE_CPU_AARCH64)
#define VENTOY_UEFI_DESC L"ARM64 UEFI"
#else
#error Unknown Processor Type
#endif
typedef struct ventoy_sector_flag
{
UINT8 flag; // 0:init 1:mem 2:remap
UINT64 remap_lba;
}ventoy_sector_flag;
typedef struct vtoy_block_data
{
EFI_HANDLE Handle;
EFI_BLOCK_IO_MEDIA Media; /* Media descriptor */
EFI_BLOCK_IO_PROTOCOL BlockIo; /* Block I/O protocol */
UINTN DevicePathCompareLen;
EFI_DEVICE_PATH_PROTOCOL *Path; /* Device path protocol */
EFI_HANDLE RawBlockIoHandle;
EFI_BLOCK_IO_PROTOCOL *pRawBlockIo;
EFI_DEVICE_PATH_PROTOCOL *pDiskDevPath;
/* ventoy disk part2 ESP */
EFI_HANDLE DiskFsHandle;
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *pDiskFs;
EFI_DEVICE_PATH_PROTOCOL *pDiskFsDevPath;
EFI_HANDLE IsoDriverImage;
}vtoy_block_data;
#define ISO9660_EFI_DRIVER_PATH L"\\ventoy\\iso9660_x64.efi"
#define debug(expr, ...) if (gDebugPrint) VtoyDebug("[VTOY] "expr"\r\n", ##__VA_ARGS__)
#define sleep(sec) gBS->Stall(1000000 * (sec))
#define ventoy_debug_pause() \
if (gDebugPrint) \
{ \
UINTN __Index = 0; \
gST->ConOut->OutputString(gST->ConOut, L"[VTOY] ###### Press Enter to continue... ######\r\n");\
gST->ConIn->Reset(gST->ConIn, FALSE); \
gBS->WaitForEvent(1, &gST->ConIn->WaitForKey, &__Index);\
}
typedef const char * (*grub_env_get_pf)(const char *name);
#pragma pack(1)
typedef struct ventoy_grub_param
{
grub_env_get_pf grub_env_get;
}ventoy_grub_param;
#pragma pack()
extern BOOLEAN gDebugPrint;
VOID EFIAPI VtoyDebug(IN CONST CHAR8 *Format, ...);
#endif
#************************************************************************************
# Copyright (c) 2020, longpanda <admin@ventoy.net>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.
#
#************************************************************************************
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = Ventoy
FILE_GUID = 1c3a0915-09dc-49c2-873d-0aaaa7733299
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
ENTRY_POINT = VentoyEfiMain
[Sources]
Ventoy.h
Ventoy.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
ShellPkg/ShellPkg.dec
[LibraryClasses]
UefiApplicationEntryPoint
UefiLib
DebugLib
[Guids]
gShellVariableGuid
[Protocols]
gEfiLoadedImageProtocolGuid
gEfiBlockIoProtocolGuid
gEfiDevicePathProtocolGuid
gEfiSimpleFileSystemProtocolGuid
## @file
# EFI/PI Reference Module Package for All Architectures
#
# (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
# Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
PLATFORM_NAME = MdeModule
PLATFORM_GUID = 587CE499-6CBE-43cd-94E2-186218569478
PLATFORM_VERSION = 0.98
DSC_SPECIFICATION = 0x00010005
OUTPUT_DIRECTORY = Build/MdeModule
SUPPORTED_ARCHITECTURES = IA32|X64|EBC|ARM|AARCH64
BUILD_TARGETS = DEBUG|RELEASE|NOOPT
SKUID_IDENTIFIER = DEFAULT
[LibraryClasses]
#
# Entry point
#
PeiCoreEntryPoint|MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf
PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
#
# Basic
#
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf
CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
SortLib|MdeModulePkg/Library/BaseSortLib/BaseSortLib.inf
#
# UEFI & PI
#
UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf
UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf
PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
#
# Generic Modules
#
UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf
CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
#
# Misc
#
DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
PlatformHookLib|MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf
ResetSystemLib|MdeModulePkg/Library/BaseResetSystemLibNull/BaseResetSystemLibNull.inf
SmbusLib|MdePkg/Library/DxeSmbusLib/DxeSmbusLib.inf
S3BootScriptLib|MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf
CpuExceptionHandlerLib|MdeModulePkg/Library/CpuExceptionHandlerLibNull/CpuExceptionHandlerLibNull.inf
PlatformBootManagerLib|MdeModulePkg/Library/PlatformBootManagerLibNull/PlatformBootManagerLibNull.inf
PciHostBridgeLib|MdeModulePkg/Library/PciHostBridgeLibNull/PciHostBridgeLibNull.inf
TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
NonDiscoverableDeviceRegistrationLib|MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf
FmpAuthenticationLib|MdeModulePkg/Library/FmpAuthenticationLibNull/FmpAuthenticationLibNull.inf
CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
BmpSupportLib|MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf
SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
DisplayUpdateProgressLib|MdeModulePkg/Library/DisplayUpdateProgressLibGraphics/DisplayUpdateProgressLibGraphics.inf
[LibraryClasses.EBC.PEIM]
IoLib|MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.inf
[LibraryClasses.common.PEI_CORE]
HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
[LibraryClasses.common.PEIM]
HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf
[LibraryClasses.common.DXE_CORE]
HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf
ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf
[LibraryClasses.common.DXE_DRIVER]
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf
CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
[LibraryClasses.common.DXE_RUNTIME_DRIVER]
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf
LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf
CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
[LibraryClasses.common.SMM_CORE]
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
MemoryAllocationLib|MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationLib.inf
SmmServicesTableLib|MdeModulePkg/Library/PiSmmCoreSmmServicesTableLib/PiSmmCoreSmmServicesTableLib.inf
SmmCorePlatformHookLib|MdeModulePkg/Library/SmmCorePlatformHookLibNull/SmmCorePlatformHookLibNull.inf
SmmMemLib|MdePkg/Library/SmmMemLib/SmmMemLib.inf
[LibraryClasses.common.DXE_SMM_DRIVER]
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
MemoryAllocationLib|MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf
MmServicesTableLib|MdePkg/Library/MmServicesTableLib/MmServicesTableLib.inf
SmmServicesTableLib|MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf
LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf
SmmMemLib|MdePkg/Library/SmmMemLib/SmmMemLib.inf
[LibraryClasses.common.UEFI_DRIVER]
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf
LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf
[LibraryClasses.common.UEFI_APPLICATION]
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
DebugLib|MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf
FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
[LibraryClasses.common.MM_STANDALONE]
HobLib|MdeModulePkg/Library/BaseHobLibNull/BaseHobLibNull.inf
MemoryAllocationLib|MdeModulePkg/Library/BaseMemoryAllocationLibNull/BaseMemoryAllocationLibNull.inf
StandaloneMmDriverEntryPoint|MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf
MmServicesTableLib|MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf
[LibraryClasses.ARM, LibraryClasses.AARCH64]
ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf
ArmMmuLib|ArmPkg/Library/ArmMmuLib/ArmMmuBaseLib.inf
LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf
#
# It is not possible to prevent ARM compiler calls to generic intrinsic functions.
# This library provides the instrinsic functions generated by a given compiler.
# [LibraryClasses.ARM] and NULL mean link this library into all ARM images.
#
NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
#
# Since software stack checking may be heuristically enabled by the compiler
# include BaseStackCheckLib unconditionally.
#
NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf
[LibraryClasses.EBC]
LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf
[PcdsFeatureFlag]
gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable|TRUE
gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable|TRUE
gEfiMdeModulePkgTokenSpaceGuid.PcdInstallAcpiSdtProtocol|TRUE
gEfiMdeModulePkgTokenSpaceGuid.PcdDevicePathSupportDevicePathFromText|FALSE
gEfiMdeModulePkgTokenSpaceGuid.PcdDevicePathSupportDevicePathToText|FALSE
[PcdsFixedAtBuild]
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x0f
gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x06
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizeNonPopulateCapsule|0x0
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizePopulateCapsule|0x0
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxPeiPerformanceLogEntries|28
[PcdsDynamicExDefault]
gEfiMdeModulePkgTokenSpaceGuid.PcdRecoveryFileName|L"FVMAIN.FV"
[Components]
MdeModulePkg/Application/Ventoy/Ventoy.inf
MdeModulePkg/Application/HelloWorld/HelloWorld.inf
MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.inf
MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf
MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
MdeModulePkg/Logo/Logo.inf
MdeModulePkg/Logo/LogoDxe.inf
MdeModulePkg/Library/BaseSortLib/BaseSortLib.inf
MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerUiLib.inf
MdeModulePkg/Library/BootManagerUiLib/BootManagerUiLib.inf
MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerUiLib.inf
MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf
MdeModulePkg/Library/PciHostBridgeLibNull/PciHostBridgeLibNull.inf
MdeModulePkg/Library/PiSmmCoreSmmServicesTableLib/PiSmmCoreSmmServicesTableLib.inf
MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
MdeModulePkg/Library/BaseHobLibNull/BaseHobLibNull.inf
MdeModulePkg/Library/BaseMemoryAllocationLibNull/BaseMemoryAllocationLibNull.inf
MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
MdeModulePkg/Bus/Pci/PciSioSerialDxe/PciSioSerialDxe.inf
MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
MdeModulePkg/Bus/Pci/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupportDxe.inf
MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf
MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf
MdeModulePkg/Bus/Pci/SdMmcPciHcPei/SdMmcPciHcPei.inf
MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcBlockIoPei.inf
MdeModulePkg/Bus/Sd/SdBlockIoPei/SdBlockIoPei.inf
MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.inf
MdeModulePkg/Bus/Sd/SdDxe/SdDxe.inf
MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.inf
MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruDxe.inf
MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.inf
MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.inf
MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf
MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf
MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf
MdeModulePkg/Bus/Pci/UhciPei/UhciPei.inf
MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf
MdeModulePkg/Bus/Pci/XhciPei/XhciPei.inf
MdeModulePkg/Bus/Pci/IdeBusPei/IdeBusPei.inf
MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf
MdeModulePkg/Bus/Usb/UsbBotPei/UsbBotPei.inf
MdeModulePkg/Bus/Pci/SataControllerDxe/SataControllerDxe.inf
MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf
MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf
MdeModulePkg/Bus/Ata/AhciPei/AhciPei.inf
MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf
MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf
MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointerDxe.inf
MdeModulePkg/Bus/Usb/UsbMouseDxe/UsbMouseDxe.inf
MdeModulePkg/Bus/I2c/I2cDxe/I2cBusDxe.inf
MdeModulePkg/Bus/I2c/I2cDxe/I2cHostDxe.inf
MdeModulePkg/Bus/I2c/I2cDxe/I2cDxe.inf
MdeModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf
MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf
MdeModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf
MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
MdeModulePkg/Core/Pei/PeiMain.inf
MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
MdeModulePkg/Library/UefiMemoryAllocationProfileLib/UefiMemoryAllocationProfileLib.inf
MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf
MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationProfileLib.inf
MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf
MdeModulePkg/Library/DxeCrc32GuidedSectionExtractLib/DxeCrc32GuidedSectionExtractLib.inf
MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf
MdeModulePkg/Library/DxeResetSystemLib/DxeResetSystemLib.inf
MdeModulePkg/Library/DxePrintLibPrint2Protocol/DxePrintLibPrint2Protocol.inf
MdeModulePkg/Library/PeiCrc32GuidedSectionExtractLib/PeiCrc32GuidedSectionExtractLib.inf
MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.inf
MdeModulePkg/Library/PeiResetSystemLib/PeiResetSystemLib.inf
MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
MdeModulePkg/Library/ResetUtilityLib/ResetUtilityLib.inf
MdeModulePkg/Library/BaseResetSystemLibNull/BaseResetSystemLibNull.inf
MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
MdeModulePkg/Library/RuntimeDxeReportStatusCodeLib/RuntimeDxeReportStatusCodeLib.inf
MdeModulePkg/Library/RuntimeResetSystemLib/RuntimeResetSystemLib.inf
MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf
MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf
MdeModulePkg/Library/DxeDebugPrintErrorLevelLib/DxeDebugPrintErrorLevelLib.inf
MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf
MdeModulePkg/Library/PeiDebugPrintHobLib/PeiDebugPrintHobLib.inf
MdeModulePkg/Library/CpuExceptionHandlerLibNull/CpuExceptionHandlerLibNull.inf
MdeModulePkg/Library/PlatformHookLibSerialPortPpi/PlatformHookLibSerialPortPpi.inf
MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
MdeModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf
MdeModulePkg/Library/PeiDebugLibDebugPpi/PeiDebugLibDebugPpi.inf
MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
MdeModulePkg/Library/PlatformBootManagerLibNull/PlatformBootManagerLibNull.inf
MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf
MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf
MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf
MdeModulePkg/Library/PlatformVarCleanupLib/PlatformVarCleanupLib.inf
MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
MdeModulePkg/Library/DxeFileExplorerProtocol/DxeFileExplorerProtocol.inf
MdeModulePkg/Library/BaseIpmiLibNull/BaseIpmiLibNull.inf
MdeModulePkg/Library/DxeIpmiLibIpmiProtocol/DxeIpmiLibIpmiProtocol.inf
MdeModulePkg/Library/PeiIpmiLibIpmiPpi/PeiIpmiLibIpmiPpi.inf
MdeModulePkg/Library/SmmIpmiLibSmmIpmiProtocol/SmmIpmiLibSmmIpmiProtocol.inf
MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf
MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf
MdeModulePkg/Library/DisplayUpdateProgressLibGraphics/DisplayUpdateProgressLibGraphics.inf
MdeModulePkg/Library/DisplayUpdateProgressLibText/DisplayUpdateProgressLibText.inf
MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenuApp.inf
MdeModulePkg/Application/UiApp/UiApp.inf{
<LibraryClasses>
NULL|MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerUiLib.inf
NULL|MdeModulePkg/Library/BootManagerUiLib/BootManagerUiLib.inf
NULL|MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerUiLib.inf
}
MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManagerDxe.inf
MdeModulePkg/Universal/BootManagerPolicyDxe/BootManagerPolicyDxe.inf
MdeModulePkg/Universal/CapsulePei/CapsulePei.inf
MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.inf
MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
MdeModulePkg/Universal/Console/GraphicsOutputDxe/GraphicsOutputDxe.inf
MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
MdeModulePkg/Universal/DebugPortDxe/DebugPortDxe.inf
MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
MdeModulePkg/Universal/PrintDxe/PrintDxe.inf
MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf
MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf
MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
MdeModulePkg/Universal/Disk/CdExpressPei/CdExpressPei.inf
MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.inf
MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
MdeModulePkg/Universal/MemoryTest/GenericMemoryTestDxe/GenericMemoryTestDxe.inf
MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf
MdeModulePkg/Universal/Metronome/Metronome.inf
MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
MdeModulePkg/Universal/ResetSystemPei/ResetSystemPei.inf {
<LibraryClasses>
ResetSystemLib|MdeModulePkg/Library/BaseResetSystemLibNull/BaseResetSystemLibNull.inf
}
MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf {
<LibraryClasses>
ResetSystemLib|MdeModulePkg/Library/BaseResetSystemLibNull/BaseResetSystemLibNull.inf
}
MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf
MdeModulePkg/Universal/SmbiosMeasurementDxe/SmbiosMeasurementDxe.inf
MdeModulePkg/Universal/PcatSingleSegmentPciCfg2Pei/PcatSingleSegmentPciCfg2Pei.inf
MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
MdeModulePkg/Universal/PCD/Pei/Pcd.inf
MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverrideDxe.inf
MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf
MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf
MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
MdeModulePkg/Application/VariableInfo/VariableInfo.inf
MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf
MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
MdeModulePkg/Universal/TimestampDxe/TimestampDxe.inf
MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatformDxe.inf
MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
MdeModulePkg/Universal/HiiResourcesSampleDxe/HiiResourcesSampleDxe.inf
MdeModulePkg/Universal/LegacyRegion2Dxe/LegacyRegion2Dxe.inf
MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf
MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf
MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.inf {
<LibraryClasses>
LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf
}
MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.inf
MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.inf
MdeModulePkg/Universal/SectionExtractionDxe/SectionExtractionDxe.inf {
<LibraryClasses>
NULL|MdeModulePkg/Library/DxeCrc32GuidedSectionExtractLib/DxeCrc32GuidedSectionExtractLib.inf
}
MdeModulePkg/Universal/SectionExtractionPei/SectionExtractionPei.inf {
<LibraryClasses>
NULL|MdeModulePkg/Library/PeiCrc32GuidedSectionExtractLib/PeiCrc32GuidedSectionExtractLib.inf
}
MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystemDxe.inf
MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxe.inf
MdeModulePkg/Universal/FileExplorerDxe/FileExplorerDxe.inf {
<LibraryClasses>
FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
}
MdeModulePkg/Universal/SerialDxe/SerialDxe.inf
MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.inf
MdeModulePkg/Universal/DebugServicePei/DebugServicePei.inf
MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
MdeModulePkg/Library/FmpAuthenticationLibNull/FmpAuthenticationLibNull.inf
MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
[Components.IA32, Components.X64, Components.AARCH64]
MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
MdeModulePkg/Universal/EbcDxe/EbcDebugger.inf
MdeModulePkg/Universal/EbcDxe/EbcDebuggerConfig.inf
[Components.IA32, Components.X64, Components.ARM, Components.AARCH64]
MdeModulePkg/Library/BrotliCustomDecompressLib/BrotliCustomDecompressLib.inf
MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf
MdeModulePkg/Core/Dxe/DxeMain.inf {
<LibraryClasses>
NULL|MdeModulePkg/Library/DxeCrc32GuidedSectionExtractLib/DxeCrc32GuidedSectionExtractLib.inf
}
!if $(TOOL_CHAIN_TAG) != "XCODE5"
MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteStandaloneMm.inf
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
!endif
[Components.IA32, Components.X64]
MdeModulePkg/Universal/DebugSupportDxe/DebugSupportDxe.inf
MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfo.inf
MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf
MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf {
<LibraryClasses>
NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf
NULL|MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf
NULL|MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf
}
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf {
<LibraryClasses>
NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf
NULL|MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf
NULL|MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf
}
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
MdeModulePkg/Library/SmmReportStatusCodeLib/SmmReportStatusCodeLib.inf
MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerSmm.inf
MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterSmm.inf
MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf
MdeModulePkg/Library/SmmMemoryAllocationProfileLib/SmmMemoryAllocationProfileLib.inf
MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationProfileLib.inf
MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationLib.inf
MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.inf
MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.inf
MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf
MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf
MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf
MdeModulePkg/Library/SmmCorePlatformHookLibNull/SmmCorePlatformHookLibNull.inf
MdeModulePkg/Library/SmmSmiHandlerProfileLib/SmmSmiHandlerProfileLib.inf
MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaArchCustomDecompressLib.inf
MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf
MdeModulePkg/Universal/Acpi/S3SaveStateDxe/S3SaveStateDxe.inf
MdeModulePkg/Universal/Acpi/SmmS3SaveState/SmmS3SaveState.inf
MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.inf
MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf
MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmDxe.inf
MdeModulePkg/Universal/RegularExpressionDxe/RegularExpressionDxe.inf
MdeModulePkg/Universal/SmmCommunicationBufferDxe/SmmCommunicationBufferDxe.inf
MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDxe.inf
[Components.X64]
MdeModulePkg/Universal/CapsulePei/CapsuleX64.inf
[BuildOptions]
*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
Please download exfat-1.3.0.zip and mirrors-libfuse-fuse-2.9.9.zip first.
exfat-1.3.0.zip:
https://codeload.github.com/relan/exfat/zip/v1.3.0
mirrors-libfuse-fuse-2.9.9.zip:
https://gitee.com/mirrors/libfuse/repository/archive/fuse-2.9.9.zip
#!/bin/bash
#
# For 32bit, for example CentOS 6.10 i386
# automake 1.11.1 must update to automake 1.11.2
# pkg-config must be installed
#
#
if uname -a | egrep -q 'x86_64|amd64'; then
opt=
else
opt=-lrt
fi
CUR="$PWD"
if ! [ -e LIBFUSE ]; then
./buidlibfuse.sh
fi
rm -f EXFAT/shared/*
rm -f EXFAT/static/*
rm -rf exfat-1.3.0
unzip exfat-1.3.0.zip
cd exfat-1.3.0
autoreconf --install
./configure --prefix="$CUR" CFLAGS='-static -O2 -D_FILE_OFFSET_BITS=64' FUSE_CFLAGS="-I$CUR/LIBFUSE/include/" FUSE_LIBS="$CUR/LIBFUSE/lib/libfuse.a -pthread $opt -ldl"
make
strip --strip-all fuse/mount.exfat-fuse
strip --strip-all mkfs/mkexfatfs
cp fuse/mount.exfat-fuse ../EXFAT/static/mount.exfat-fuse
cp mkfs/mkexfatfs ../EXFAT/static/mkexfatfs
cd ..
rm -rf exfat-1.3.0
unzip exfat-1.3.0.zip
cd exfat-1.3.0
autoreconf --install
./configure --prefix="$CUR" CFLAGS='-O2 -D_FILE_OFFSET_BITS=64' FUSE_CFLAGS="-I$CUR/LIBFUSE/include/" FUSE_LIBS="$CUR/LIBFUSE/lib/libfuse.a -lpthread -ldl $opt"
make
strip --strip-all fuse/mount.exfat-fuse
strip --strip-all mkfs/mkexfatfs
cp fuse/mount.exfat-fuse ../EXFAT/shared/mount.exfat-fuse
cp mkfs/mkexfatfs ../EXFAT/shared/mkexfatfs
cd ..
rm -rf exfat-1.3.0
#!/bin/bash
CUR="$PWD"
rm -rf libfuse
rm -rf LIBFUSE
unzip mirrors-libfuse-fuse-2.9.9.zip
cd libfuse
./makeconf.sh
./configure --prefix="$CUR/LIBFUSE"
make -j 16
make install
cd ..
rm -rf libfuse
#!/bin/bash
CUR="$PWD"
#LIBFUSE_DIR=$CUR/LIBFUSE
LIBFUSE_DIR=../ExFAT/LIBFUSE
if uname -a | egrep -q 'x86_64|amd64'; then
name=vtoy_fuse_iso_64
else
name=vtoy_fuse_iso_32
opt=-lrt
fi
export C_INCLUDE_PATH=$LIBFUSE_DIR/include
rm -f $name
gcc -O2 -D_FILE_OFFSET_BITS=64 vtoy_fuse_iso.c -o $name $LIBFUSE_DIR/lib/libfuse.a -lpthread -ldl $opt
if [ -e $name ]; then
echo -e "\n############### SUCCESS $name ##################\n"
else
echo -e "\n############### FAILED $name ##################\n"
fi
strip --strip-all $name
#!/bin/bash
#
#
# Package Dependency:
# gcc automake autoconf gettext gettext-devel libtool unzip
#
#
CUR="$PWD"
LIBFUSE_DIR=$CUR/LIBFUSE
rm -rf libfuse
rm -rf $LIBFUSE_DIR
# please download https://gitee.com/mirrors/libfuse/repository/archive/fuse-2.9.9.zip
if ! [ -e mirrors-libfuse-fuse-2.9.9.zip ]; then
echo "Please download mirrors-libfuse-fuse-2.9.9.zip first"
exit 1
fi
unzip mirrors-libfuse-fuse-2.9.9.zip
cd libfuse
./makeconf.sh
./configure --prefix="$LIBFUSE_DIR"
make -j 16
make install
cd ..
rm -rf libfuse
/******************************************************************************
* vtoy_fuse_iso.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/>.
*
*/
#define FUSE_USE_VERSION 26
#include <fuse.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
typedef unsigned int uint32_t;
typedef struct dmtable_entry
{
uint32_t isoSector;
uint32_t sectorNum;
unsigned long long diskSector;
}dmtable_entry;
#define MAX_ENTRY_NUM (1024 * 1024 / sizeof(dmtable_entry))
static int verbose = 0;
#define debug(fmt, ...) if(verbose) printf(fmt, ##__VA_ARGS__)
static int g_disk_fd = -1;
static uint64_t g_iso_file_size;
static char g_mnt_point[512];
static char g_iso_file_name[512];
static dmtable_entry *g_disk_entry_list = NULL;
static int g_disk_entry_num = 0;
static int ventoy_iso_getattr(const char *path, struct stat *statinfo)
{
int ret = -ENOENT;
if (path && statinfo)
{
memset(statinfo, 0, sizeof(struct stat));
if (path[0] == '/' && path[1] == 0)
{
statinfo->st_mode = S_IFDIR | 0755;
statinfo->st_nlink = 2;
ret = 0;
}
else if (strcmp(path, g_iso_file_name) == 0)
{
statinfo->st_mode = S_IFREG | 0444;
statinfo->st_nlink = 1;
statinfo->st_size = g_iso_file_size;
ret = 0;
}
}
return ret;
}
static int ventoy_iso_readdir
(
const char *path,
void *buf,
fuse_fill_dir_t filler,
off_t offset,
struct fuse_file_info *file
)
{
(void)offset;
(void)file;
if (path[0] != '/' || path[1] != 0)
{
return -ENOENT;
}
filler(buf, ".", NULL, 0);
filler(buf, "..", NULL, 0);
filler(buf, g_iso_file_name + 1, NULL, 0);
return 0;
}
static int ventoy_iso_open(const char *path, struct fuse_file_info *file)
{
if (strcmp(path, g_iso_file_name) != 0)
{
return -ENOENT;
}
if ((file->flags & 3) != O_RDONLY)
{
return -EACCES;
}
return 0;
}
static int ventoy_read_iso_sector(uint32_t sector, uint32_t num, void *buf)
{
uint32_t i = 0;
uint32_t leftSec = 0;
uint32_t readSec = 0;
dmtable_entry *entry = NULL;
for (i = 0; i < g_disk_entry_num && num > 0; i++)
{
entry = g_disk_entry_list + i;
if (sector >= entry->isoSector && sector < entry->isoSector + entry->sectorNum)
{
lseek(g_disk_fd, (entry->diskSector + (sector - entry->isoSector)) * 512, SEEK_SET);
leftSec = entry->sectorNum - (sector - entry->isoSector);
readSec = (leftSec > num) ? num : leftSec;
read(g_disk_fd, buf, readSec * 512);
sector += readSec;
num -= readSec;
}
}
return 0;
}
static int ventoy_iso_read
(
const char *path, char *buf,
size_t size, off_t offset,
struct fuse_file_info *file
)
{
uint32_t mod = 0;
uint32_t align = 0;
uint32_t sector = 0;
uint32_t number = 0;
size_t leftsize = 0;
char secbuf[512];
(void)file;
if(strcmp(path, g_iso_file_name) != 0)
{
return -ENOENT;
}
if (offset >= g_iso_file_size)
{
return 0;
}
if (offset + size > g_iso_file_size)
{
size = g_iso_file_size - offset;
}
leftsize = size;
sector = offset / 512;
mod = offset % 512;
if (mod > 0)
{
align = 512 - mod;
ventoy_read_iso_sector(sector, 1, secbuf);
if (leftsize > align)
{
memcpy(buf, secbuf + mod, align);
buf += align;
offset += align;
sector++;
leftsize -= align;
}
else
{
memcpy(buf, secbuf + mod, leftsize);
return size;
}
}
number = leftsize / 512;
ventoy_read_iso_sector(sector, number, buf);
buf += number * 512;
mod = leftsize % 512;
if (mod > 0)
{
ventoy_read_iso_sector(sector + number, 1, secbuf);
memcpy(buf, secbuf, mod);
}
return size;
}
static struct fuse_operations ventoy_op =
{
.getattr = ventoy_iso_getattr,
.readdir = ventoy_iso_readdir,
.open = ventoy_iso_open,
.read = ventoy_iso_read,
};
static int ventoy_parse_dmtable(const char *filename)
{
FILE *fp = NULL;
char diskname[128] = {0};
char line[256] = {0};
dmtable_entry *entry= g_disk_entry_list;
fp = fopen(filename, "r");
if (NULL == fp)
{
printf("Failed to open file %s\n", filename);
return 1;
}
/* read untill the last line */
while (fgets(line, sizeof(line), fp) && g_disk_entry_num < MAX_ENTRY_NUM)
{
sscanf(line, "%u %u linear %s %llu",
&entry->isoSector, &entry->sectorNum,
diskname, &entry->diskSector);
g_iso_file_size += (uint64_t)entry->sectorNum * 512ULL;
g_disk_entry_num++;
entry++;
}
fclose(fp);
if (g_disk_entry_num >= MAX_ENTRY_NUM)
{
fprintf(stderr, "ISO file has too many fragments ( more than %u )\n", MAX_ENTRY_NUM);
return 1;
}
debug("iso file size: %llu disk name %s\n", g_iso_file_size, diskname);
g_disk_fd = open(diskname, O_RDONLY);
if (g_disk_fd < 0)
{
debug("Failed to open %s\n", diskname);
return 1;
}
return 0;
}
int main(int argc, char **argv)
{
int rc;
int ch;
char filename[512] = {0};
/* Avoid to be killed by systemd */
if (access("/etc/initrd-release", F_OK) >= 0)
{
argv[0][0] = '@';
}
g_iso_file_name[0] = '/';
while ((ch = getopt(argc, argv, "f:s:m:v::t::")) != -1)
{
if (ch == 'f')
{
strncpy(filename, optarg, sizeof(filename) - 1);
}
else if (ch == 'm')
{
strncpy(g_mnt_point, optarg, sizeof(g_mnt_point) - 1);
}
else if (ch == 's')
{
strncpy(g_iso_file_name + 1, optarg, sizeof(g_iso_file_name) - 2);
}
else if (ch == 'v')
{
verbose = 1;
}
else if (ch == 't') // for test
{
return 0;
}
}
if (filename[0] == 0)
{
fprintf(stderr, "Must input dmsetup table file with -f\n");
return 1;
}
if (g_mnt_point[0] == 0)
{
fprintf(stderr, "Must input mount point with -m\n");
return 1;
}
if (g_iso_file_name[1] == 0)
{
strncpy(g_iso_file_name + 1, "ventoy.iso", sizeof(g_iso_file_name) - 2);
}
debug("ventoy fuse iso: %s %s %s\n", filename, g_iso_file_name, g_mnt_point);
g_disk_entry_list = malloc(MAX_ENTRY_NUM * sizeof(dmtable_entry));
if (NULL == g_disk_entry_list)
{
return 1;
}
rc = ventoy_parse_dmtable(filename);
if (rc)
{
free(g_disk_entry_list);
return rc;
}
argv[1] = g_mnt_point;
argv[2] = NULL;
rc = fuse_main(2, argv, &ventoy_op, NULL);
close(g_disk_fd);
free(g_disk_entry_list);
return rc;
}
========== About Source Code =============
Ventoy use grub-2.04, so I only put the added and modified source code here.
You can download grub-2.04 source code from this site:
https://ftp.gnu.org/gnu/grub/
Just merge the code here with the original code of grub-2.04
========== Build =============
./autogen.sh
./configure
make
AutoGen definitions Makefile.tpl;
transform_data = {
installdir = noinst;
name = gensyminfo.sh;
common = gensyminfo.sh.in;
};
transform_data = {
installdir = noinst;
name = genmod.sh;
common = genmod.sh.in;
};
transform_data = {
installdir = noinst;
name = modinfo.sh;
common = modinfo.sh.in;
};
transform_data = {
installdir = platform;
name = gmodule.pl;
common = gmodule.pl.in;
};
transform_data = {
installdir = platform;
name = gdb_grub;
common = gdb_grub.in;
};
transform_data = {
installdir = platform;
name = grub.chrp;
common = boot/powerpc/grub.chrp.in;
enable = powerpc_ieee1275;
};
transform_data = {
installdir = platform;
name = bootinfo.txt;
common = boot/powerpc/bootinfo.txt.in;
enable = powerpc_ieee1275;
};
kernel = {
name = kernel;
nostrip = emu;
emu_ldflags = '-Wl,-r,-d';
i386_efi_ldflags = '-Wl,-r,-d';
i386_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version';
x86_64_efi_ldflags = '-Wl,-r,-d';
x86_64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version';
ia64_efi_cflags = '-fno-builtin -fpic -minline-int-divide-max-throughput';
ia64_efi_ldflags = '-Wl,-r,-d';
ia64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version';
arm_efi_ldflags = '-Wl,-r,-d';
arm_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version';
arm64_efi_ldflags = '-Wl,-r,-d';
arm64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version -R .eh_frame';
riscv32_efi_ldflags = '-Wl,-r,-d';
riscv32_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version -R .eh_frame';
riscv64_efi_ldflags = '-Wl,-r,-d';
riscv64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version -R .eh_frame';
i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)';
i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x9000';
i386_qemu_ldflags = '$(TARGET_IMG_LDFLAGS)';
i386_qemu_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x9000';
i386_coreboot_ldflags = '$(TARGET_IMG_LDFLAGS)';
i386_coreboot_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x9000';
i386_multiboot_ldflags = '$(TARGET_IMG_LDFLAGS)';
i386_multiboot_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x9000';
i386_ieee1275_ldflags = '$(TARGET_IMG_LDFLAGS)';
i386_ieee1275_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x10000';
i386_xen_ldflags = '$(TARGET_IMG_LDFLAGS)';
i386_xen_ldflags = '$(TARGET_IMG_BASE_LDOPT),0';
x86_64_xen_ldflags = '$(TARGET_IMG_LDFLAGS)';
x86_64_xen_ldflags = '$(TARGET_IMG_BASE_LDOPT),0';
i386_xen_pvh_ldflags = '$(TARGET_IMG_LDFLAGS)';
i386_xen_pvh_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x100000';
mips_loongson_ldflags = '-Wl,-Ttext,0x80200000';
powerpc_ieee1275_ldflags = '-Wl,-Ttext,0x200000';
sparc64_ieee1275_ldflags = '-Wl,-Ttext,0x4400';
mips_arc_ldflags = '-Wl,-Ttext,$(TARGET_LINK_ADDR)';
mips_qemu_mips_ldflags = '-Wl,-Ttext,0x80200000';
mips_arc_cppflags = '-DGRUB_DECOMPRESSOR_LINK_ADDR=$(TARGET_DECOMPRESSOR_LINK_ADDR)';
i386_qemu_cppflags = '-DGRUB_BOOT_MACHINE_LINK_ADDR=$(GRUB_BOOT_MACHINE_LINK_ADDR)';
emu_cflags = '$(CFLAGS_GNULIB)';
emu_cppflags = '$(CPPFLAGS_GNULIB)';
arm_uboot_ldflags = '-Wl,-r,-d';
arm_uboot_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version';
arm_coreboot_ldflags = '-Wl,-r,-d';
arm_coreboot_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version';
i386_pc_startup = kern/i386/pc/startup.S;
i386_efi_startup = kern/i386/efi/startup.S;
x86_64_efi_startup = kern/x86_64/efi/startup.S;
i386_xen_startup = kern/i386/xen/startup.S;
x86_64_xen_startup = kern/x86_64/xen/startup.S;
i386_xen_pvh_startup = kern/i386/xen/startup_pvh.S;
i386_qemu_startup = kern/i386/qemu/startup.S;
i386_ieee1275_startup = kern/i386/ieee1275/startup.S;
i386_coreboot_startup = kern/i386/coreboot/startup.S;
i386_multiboot_startup = kern/i386/coreboot/startup.S;
mips_startup = kern/mips/startup.S;
sparc64_ieee1275_startup = kern/sparc64/ieee1275/crt0.S;
powerpc_ieee1275_startup = kern/powerpc/ieee1275/startup.S;
arm_uboot_startup = kern/arm/startup.S;
arm_coreboot_startup = kern/arm/startup.S;
arm_efi_startup = kern/arm/efi/startup.S;
arm64_efi_startup = kern/arm64/efi/startup.S;
riscv32_efi_startup = kern/riscv/efi/startup.S;
riscv64_efi_startup = kern/riscv/efi/startup.S;
common = kern/command.c;
common = kern/corecmd.c;
common = kern/device.c;
common = kern/disk.c;
common = kern/dl.c;
common = kern/env.c;
common = kern/err.c;
common = kern/file.c;
common = kern/fs.c;
common = kern/list.c;
common = kern/main.c;
common = kern/misc.c;
common = kern/parser.c;
common = kern/partition.c;
common = kern/rescue_parser.c;
common = kern/rescue_reader.c;
common = kern/term.c;
noemu = kern/compiler-rt.c;
noemu = kern/mm.c;
noemu = kern/time.c;
noemu = kern/generic/millisleep.c;
noemu_nodist = symlist.c;
mips = kern/generic/rtc_get_time_ms.c;
ieee1275 = disk/ieee1275/ofdisk.c;
ieee1275 = kern/ieee1275/cmain.c;
ieee1275 = kern/ieee1275/ieee1275.c;
ieee1275 = kern/ieee1275/mmap.c;
ieee1275 = kern/ieee1275/openfw.c;
ieee1275 = term/ieee1275/console.c;
ieee1275 = kern/ieee1275/init.c;
uboot = disk/uboot/ubootdisk.c;
uboot = kern/uboot/uboot.c;
uboot = kern/uboot/init.c;
uboot = kern/uboot/hw.c;
uboot = term/uboot/console.c;
arm_uboot = kern/arm/uboot/init.c;
arm_uboot = kern/arm/uboot/uboot.S;
arm_coreboot = kern/arm/coreboot/init.c;
arm_coreboot = kern/arm/coreboot/timer.c;
arm_coreboot = kern/arm/coreboot/coreboot.S;
arm_coreboot = lib/fdt.c;
arm_coreboot = bus/fdt.c;
arm_coreboot = term/ps2.c;
arm_coreboot = term/arm/pl050.c;
arm_coreboot = term/arm/cros.c;
arm_coreboot = term/arm/cros_ec.c;
arm_coreboot = bus/spi/rk3288_spi.c;
arm_coreboot = commands/keylayouts.c;
arm_coreboot = kern/arm/coreboot/dma.c;
terminfoinkernel = term/terminfo.c;
terminfoinkernel = term/tparm.c;
terminfoinkernel = commands/extcmd.c;
terminfoinkernel = lib/arg.c;
softdiv = lib/division.c;
i386 = kern/i386/dl.c;
i386_xen = kern/i386/dl.c;
i386_xen_pvh = kern/i386/dl.c;
i386_coreboot = kern/i386/coreboot/init.c;
i386_multiboot = kern/i386/coreboot/init.c;
i386_qemu = kern/i386/qemu/init.c;
i386_coreboot_multiboot_qemu = term/i386/pc/vga_text.c;
coreboot = video/coreboot/cbfb.c;
efi = disk/efi/efidisk.c;
efi = kern/efi/efi.c;
efi = kern/efi/init.c;
efi = kern/efi/mm.c;
efi = term/efi/console.c;
efi = kern/acpi.c;
efi = kern/efi/acpi.c;
i386_coreboot = kern/i386/pc/acpi.c;
i386_multiboot = kern/i386/pc/acpi.c;
i386_coreboot = kern/acpi.c;
i386_multiboot = kern/acpi.c;
x86 = kern/i386/tsc.c;
x86 = kern/i386/tsc_pit.c;
i386_efi = kern/i386/efi/tsc.c;
x86_64_efi = kern/i386/efi/tsc.c;
i386_efi = kern/i386/tsc_pmtimer.c;
i386_coreboot = kern/i386/tsc_pmtimer.c;
x86_64_efi = kern/i386/tsc_pmtimer.c;
i386_efi = kern/i386/efi/init.c;
i386_efi = bus/pci.c;
x86_64 = kern/x86_64/dl.c;
x86_64_xen = kern/x86_64/dl.c;
x86_64_efi = kern/x86_64/efi/callwrap.S;
x86_64_efi = kern/i386/efi/init.c;
x86_64_efi = bus/pci.c;
xen = kern/i386/tsc.c;
xen = kern/i386/xen/tsc.c;
x86_64_xen = kern/x86_64/xen/hypercall.S;
i386_xen = kern/i386/xen/hypercall.S;
xen = kern/xen/init.c;
xen = term/xen/console.c;
xen = disk/xen/xendisk.c;
xen = commands/boot.c;
i386_xen_pvh = commands/boot.c;
i386_xen_pvh = disk/xen/xendisk.c;
i386_xen_pvh = kern/i386/tsc.c;
i386_xen_pvh = kern/i386/xen/tsc.c;
i386_xen_pvh = kern/i386/xen/pvh.c;
i386_xen_pvh = kern/xen/init.c;
i386_xen_pvh = term/xen/console.c;
ia64_efi = kern/ia64/efi/startup.S;
ia64_efi = kern/ia64/efi/init.c;
ia64_efi = kern/ia64/dl.c;
ia64_efi = kern/ia64/dl_helper.c;
ia64_efi = kern/ia64/cache.c;
arm_efi = kern/arm/efi/init.c;
arm_efi = kern/efi/fdt.c;
arm64_efi = kern/arm64/efi/init.c;
arm64_efi = kern/efi/fdt.c;
riscv32_efi = kern/riscv/efi/init.c;
riscv32_efi = kern/efi/fdt.c;
riscv64_efi = kern/riscv/efi/init.c;
riscv64_efi = kern/efi/fdt.c;
i386_pc = kern/i386/pc/init.c;
i386_pc = kern/i386/pc/mmap.c;
i386_pc = term/i386/pc/console.c;
i386_qemu = bus/pci.c;
i386_qemu = kern/vga_init.c;
i386_qemu = kern/i386/qemu/mmap.c;
coreboot = kern/coreboot/mmap.c;
i386_coreboot = kern/i386/coreboot/cbtable.c;
coreboot = kern/coreboot/cbtable.c;
arm_coreboot = kern/arm/coreboot/cbtable.c;
i386_multiboot = kern/i386/multiboot_mmap.c;
mips = kern/mips/cache.S;
mips = kern/mips/dl.c;
mips = kern/mips/init.c;
mips_qemu_mips = kern/mips/qemu_mips/init.c;
mips_qemu_mips = term/ns8250.c;
mips_qemu_mips = term/serial.c;
mips_qemu_mips = term/at_keyboard.c;
mips_qemu_mips = term/ps2.c;
mips_qemu_mips = commands/boot.c;
mips_qemu_mips = commands/keylayouts.c;
mips_qemu_mips = term/i386/pc/vga_text.c;
mips_qemu_mips = kern/vga_init.c;
mips_arc = kern/mips/arc/init.c;
mips_arc = term/arc/console.c;
mips_arc = disk/arc/arcdisk.c;
mips_loongson = term/ns8250.c;
mips_loongson = bus/bonito.c;
mips_loongson = bus/cs5536.c;
mips_loongson = bus/pci.c;
mips_loongson = kern/mips/loongson/init.c;
mips_loongson = term/at_keyboard.c;
mips_loongson = term/ps2.c;
mips_loongson = commands/boot.c;
mips_loongson = term/serial.c;
mips_loongson = video/sm712.c;
mips_loongson = video/sis315pro.c;
mips_loongson = video/radeon_fuloong2e.c;
mips_loongson = video/radeon_yeeloong3a.c;
extra_dist = video/sm712_init.c;
extra_dist = video/sis315_init.c;
mips_loongson = commands/keylayouts.c;
powerpc_ieee1275 = kern/powerpc/cache.S;
powerpc_ieee1275 = kern/powerpc/dl.c;
powerpc_ieee1275 = kern/powerpc/compiler-rt.S;
sparc64_ieee1275 = kern/sparc64/cache.S;
sparc64_ieee1275 = kern/sparc64/dl.c;
sparc64_ieee1275 = kern/sparc64/ieee1275/ieee1275.c;
sparc64_ieee1275 = disk/ieee1275/obdisk.c;
arm = kern/arm/dl.c;
arm = kern/arm/dl_helper.c;
arm = kern/arm/cache_armv6.S;
arm = kern/arm/cache_armv7.S;
extra_dist = kern/arm/cache.S;
arm = kern/arm/cache.c;
arm = kern/arm/compiler-rt.S;
arm64 = kern/arm64/cache.c;
arm64 = kern/arm64/cache_flush.S;
arm64 = kern/arm64/dl.c;
arm64 = kern/arm64/dl_helper.c;
riscv32 = kern/riscv/cache.c;
riscv32 = kern/riscv/cache_flush.S;
riscv32 = kern/riscv/dl.c;
riscv64 = kern/riscv/cache.c;
riscv64 = kern/riscv/cache_flush.S;
riscv64 = kern/riscv/dl.c;
emu = disk/host.c;
emu = kern/emu/cache_s.S;
emu = kern/emu/hostdisk.c;
emu = osdep/unix/hostdisk.c;
emu = osdep/exec.c;
extra_dist = osdep/unix/exec.c;
emu = osdep/devmapper/hostdisk.c;
emu = osdep/hostdisk.c;
emu = kern/emu/hostfs.c;
emu = kern/emu/main.c;
emu = kern/emu/argp_common.c;
emu = kern/emu/misc.c;
emu = kern/emu/mm.c;
emu = kern/emu/time.c;
emu = kern/emu/cache.c;
emu = osdep/emuconsole.c;
extra_dist = osdep/unix/emuconsole.c;
extra_dist = osdep/windows/emuconsole.c;
emu = osdep/dl.c;
extra_dist = osdep/unix/dl.c;
extra_dist = osdep/windows/dl.c;
emu = osdep/sleep.c;
emu = osdep/init.c;
emu = osdep/emunet.c;
extra_dist = osdep/linux/emunet.c;
extra_dist = osdep/basic/emunet.c;
emu = osdep/cputime.c;
extra_dist = osdep/unix/cputime.c;
extra_dist = osdep/windows/cputime.c;
videoinkernel = term/gfxterm.c;
videoinkernel = font/font.c;
videoinkernel = font/font_cmd.c;
videoinkernel = io/bufio.c;
videoinkernel = video/fb/fbblit.c;
videoinkernel = video/fb/fbfill.c;
videoinkernel = video/fb/fbutil.c;
videoinkernel = video/fb/video_fb.c;
videoinkernel = video/video.c;
extra_dist = kern/i386/int.S;
extra_dist = kern/i386/realmode.S;
extra_dist = boot/i386/pc/lzma_decode.S;
extra_dist = kern/mips/cache_flush.S;
};
program = {
name = grub-emu;
mansection = 1;
emu = kern/emu/full.c;
emu_nodist = grub_emu_init.c;
ldadd = 'kernel.exec$(EXEEXT)';
ldadd = '$(MODULE_FILES)';
ldadd = 'lib/gnulib/libgnu.a $(LIBINTL) $(LIBUTIL) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
enable = emu;
};
program = {
name = grub-emu-lite;
emu = kern/emu/lite.c;
emu_nodist = symlist.c;
ldadd = 'kernel.exec$(EXEEXT)';
ldadd = 'lib/gnulib/libgnu.a $(LIBINTL) $(LIBUTIL) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
enable = emu;
};
image = {
name = boot;
i386_pc = boot/i386/pc/boot.S;
i386_qemu = boot/i386/qemu/boot.S;
sparc64_ieee1275 = boot/sparc64/ieee1275/boot.S;
i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)';
i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x7C00';
i386_qemu_ldflags = '$(TARGET_IMG_LDFLAGS)';
i386_qemu_ldflags = '$(TARGET_IMG_BASE_LDOPT),$(GRUB_BOOT_MACHINE_LINK_ADDR)';
i386_qemu_ccasflags = '-DGRUB_BOOT_MACHINE_LINK_ADDR=$(GRUB_BOOT_MACHINE_LINK_ADDR)';
/* The entry point for a.out binaries on sparc64 starts
at 0x4000. Since we are writing the 32 bytes long a.out
header in the assembly code ourselves, we need to tell
the linker to adjust the start of the text segment to
0x4000 - 0x20 = 0x3fe0.
*/
sparc64_ieee1275_ldflags = ' -Wl,-Ttext=0x3fe0';
sparc64_ieee1275_objcopyflags = '-O binary';
objcopyflags = '-O binary';
enable = i386_pc;
enable = i386_qemu;
enable = sparc64_ieee1275;
};
image = {
name = boot_hybrid;
i386_pc = boot/i386/pc/boot.S;
cppflags = '-DHYBRID_BOOT=1';
i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)';
i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x7C00';
objcopyflags = '-O binary';
enable = i386_pc;
};
image = {
name = cdboot;
i386_pc = boot/i386/pc/cdboot.S;
i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)';
i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x7C00';
sparc64_ieee1275 = boot/sparc64/ieee1275/boot.S;
/* See comment for sparc64_ieee1275_ldflags above. */
sparc64_ieee1275_ldflags = ' -Wl,-Ttext=0x3fe0';
sparc64_ieee1275_objcopyflags = '-O binary';
sparc64_ieee1275_cppflags = '-DCDBOOT=1';
objcopyflags = '-O binary';
enable = sparc64_ieee1275;
enable = i386_pc;
};
image = {
name = pxeboot;
i386_pc = boot/i386/pc/pxeboot.S;
i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)';
i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x7C00';
objcopyflags = '-O binary';
enable = i386_pc;
};
image = {
name = diskboot;
i386_pc = boot/i386/pc/diskboot.S;
i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)';
i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x8000';
sparc64_ieee1275 = boot/sparc64/ieee1275/diskboot.S;
sparc64_ieee1275_ldflags = '-Wl,-Ttext=0x4200';
objcopyflags = '-O binary';
enable = i386_pc;
enable = sparc64_ieee1275;
};
image = {
name = lnxboot;
i386_pc = boot/i386/pc/lnxboot.S;
i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)';
i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x6000';
objcopyflags = '-O binary';
enable = i386_pc;
};
image = {
name = xz_decompress;
mips = boot/mips/startup_raw.S;
common = boot/decompressor/minilib.c;
common = boot/decompressor/xz.c;
common = lib/xzembed/xz_dec_bcj.c;
common = lib/xzembed/xz_dec_lzma2.c;
common = lib/xzembed/xz_dec_stream.c;
common = kern/compiler-rt.c;
cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed -DGRUB_EMBED_DECOMPRESSOR=1';
objcopyflags = '-O binary';
mips_ldflags = '-Wl,-Ttext,$(TARGET_DECOMPRESSOR_LINK_ADDR)';
cflags = '-Wno-unreachable-code';
enable = mips;
};
image = {
name = none_decompress;
mips = boot/mips/startup_raw.S;
common = boot/decompressor/none.c;
cppflags = '-DGRUB_EMBED_DECOMPRESSOR=1';
objcopyflags = '-O binary';
mips_ldflags = '-Wl,-Ttext,$(TARGET_DECOMPRESSOR_LINK_ADDR)';
enable = mips;
};
image = {
name = lzma_decompress;
i386_pc = boot/i386/pc/startup_raw.S;
i386_pc_nodist = rs_decoder.h;
objcopyflags = '-O binary';
ldflags = '$(TARGET_IMG_LDFLAGS) $(TARGET_IMG_BASE_LDOPT),0x8200';
enable = i386_pc;
};
image = {
name = fwstart;
mips_loongson = boot/mips/loongson/fwstart.S;
objcopyflags = '-O binary';
ldflags = '-Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic';
enable = mips_loongson;
};
image = {
name = fwstart_fuloong2f;
mips_loongson = boot/mips/loongson/fuloong2f.S;
objcopyflags = '-O binary';
ldflags = '-Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic';
enable = mips_loongson;
};
module = {
name = disk;
common = lib/disk.c;
extra_dist = kern/disk_common.c;
};
module = {
name = trig;
common_nodist = trigtables.c;
extra_dist = gentrigtables.c;
};
module = {
name = cs5536;
x86 = bus/cs5536.c;
enable = x86;
};
module = {
name = lsspd;
mips_loongson = commands/mips/loongson/lsspd.c;
enable = mips_loongson;
};
module = {
name = usb;
common = bus/usb/usb.c;
common = bus/usb/usbtrans.c;
common = bus/usb/usbhub.c;
enable = usb;
};
module = {
name = usbserial_common;
common = bus/usb/serial/common.c;
enable = usb;
};
module = {
name = usbserial_pl2303;
common = bus/usb/serial/pl2303.c;
enable = usb;
};
module = {
name = usbserial_ftdi;
common = bus/usb/serial/ftdi.c;
enable = usb;
};
module = {
name = usbserial_usbdebug;
common = bus/usb/serial/usbdebug_late.c;
enable = usb;
};
module = {
name = uhci;
common = bus/usb/uhci.c;
enable = pci;
};
module = {
name = ohci;
common = bus/usb/ohci.c;
enable = pci;
};
module = {
name = ehci;
common = bus/usb/ehci.c;
arm_coreboot = bus/usb/ehci-fdt.c;
pci = bus/usb/ehci-pci.c;
enable = pci;
enable = arm_coreboot;
};
module = {
name = pci;
common = bus/pci.c;
i386_ieee1275 = bus/i386/ieee1275/pci.c;
enable = i386_pc;
enable = i386_ieee1275;
enable = i386_coreboot;
enable = i386_multiboot;
};
module = {
name = nativedisk;
common = commands/nativedisk.c;
enable = x86;
enable = mips_loongson;
enable = mips_qemu_mips;
};
module = {
name = emupci;
common = bus/emu/pci.c;
common = commands/lspci.c;
enable = emu;
condition = COND_GRUB_EMU_PCI;
};
module = {
name = lsdev;
common = commands/arc/lsdev.c;
enable = mips_arc;
};
module = {
name = lsxen;
common = commands/xen/lsxen.c;
enable = xen;
};
module = {
name = cmostest;
common = commands/i386/cmostest.c;
enable = cmos;
};
module = {
name = cmosdump;
common = commands/i386/cmosdump.c;
enable = cmos;
};
module = {
name = iorw;
common = commands/iorw.c;
enable = x86;
};
module = {
name = cbtable;
common = kern/i386/coreboot/cbtable.c;
common = kern/coreboot/cbtable.c;
enable = i386_pc;
enable = i386_efi;
enable = i386_qemu;
enable = i386_multiboot;
enable = i386_ieee1275;
enable = x86_64_efi;
};
module = {
name = cbtime;
common = commands/i386/coreboot/cb_timestamps.c;
enable = x86;
};
module = {
name = cbls;
common = commands/i386/coreboot/cbls.c;
enable = x86;
};
module = {
name = cbmemc;
common = term/i386/coreboot/cbmemc.c;
enable = x86;
};
module = {
name = regexp;
common = commands/regexp.c;
common = commands/wildcard.c;
common = lib/gnulib/regex.c;
cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)';
cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB)';
};
module = {
name = acpi;
common = commands/acpi.c;
i386_pc = kern/acpi.c;
i386_pc = kern/i386/pc/acpi.c;
enable = efi;
enable = i386_pc;
enable = i386_coreboot;
enable = i386_multiboot;
};
module = {
name = lsacpi;
common = commands/lsacpi.c;
enable = efi;
enable = i386_pc;
enable = i386_coreboot;
enable = i386_multiboot;
};
module = {
name = lsefisystab;
common = commands/efi/lsefisystab.c;
enable = efi;
};
module = {
name = lssal;
common = commands/efi/lssal.c;
enable = efi;
};
module = {
name = lsefimmap;
common = commands/efi/lsefimmap.c;
enable = efi;
};
module = {
name = lsefi;
common = commands/efi/lsefi.c;
enable = efi;
};
module = {
name = efifwsetup;
efi = commands/efi/efifwsetup.c;
enable = efi;
};
module = {
name = blocklist;
common = commands/blocklist.c;
};
module = {
name = boot;
common = commands/boot.c;
i386_pc = lib/i386/pc/biosnum.c;
enable = x86;
enable = emu;
enable = sparc64_ieee1275;
enable = powerpc_ieee1275;
enable = mips_arc;
enable = ia64_efi;
enable = arm_efi;
enable = arm64_efi;
enable = arm_uboot;
enable = arm_coreboot;
enable = riscv32_efi;
enable = riscv64_efi;
};
module = {
name = cat;
common = commands/cat.c;
};
module = {
name = cmp;
common = commands/cmp.c;
};
module = {
name = configfile;
common = commands/configfile.c;
};
module = {
name = cpuid;
common = commands/i386/cpuid.c;
enable = x86;
enable = i386_xen_pvh;
enable = i386_xen;
enable = x86_64_xen;
};
module = {
name = date;
common = commands/date.c;
};
module = {
name = drivemap;
i386_pc = commands/i386/pc/drivemap.c;
i386_pc = commands/i386/pc/drivemap_int13h.S;
enable = i386_pc;
};
module = {
name = echo;
common = commands/echo.c;
};
module = {
name = eval;
common = commands/eval.c;
};
module = {
name = extcmd;
common = commands/extcmd.c;
common = lib/arg.c;
enable = terminfomodule;
};
module = {
name = fixvideo;
common = commands/efi/fixvideo.c;
enable = i386_efi;
enable = x86_64_efi;
};
module = {
name = gptsync;
common = commands/gptsync.c;
};
module = {
name = halt;
nopc = commands/halt.c;
i386_pc = commands/i386/pc/halt.c;
i386_pc = commands/acpihalt.c;
i386_coreboot = commands/acpihalt.c;
i386_multiboot = commands/acpihalt.c;
i386_efi = commands/acpihalt.c;
x86_64_efi = commands/acpihalt.c;
i386_multiboot = lib/i386/halt.c;
i386_coreboot = lib/i386/halt.c;
i386_qemu = lib/i386/halt.c;
xen = lib/xen/halt.c;
i386_xen_pvh = lib/xen/halt.c;
efi = lib/efi/halt.c;
ieee1275 = lib/ieee1275/halt.c;
emu = lib/emu/halt.c;
uboot = lib/dummy/halt.c;
arm_coreboot = lib/dummy/halt.c;
};
module = {
name = reboot;
i386 = lib/i386/reboot.c;
i386 = lib/i386/reboot_trampoline.S;
powerpc_ieee1275 = lib/ieee1275/reboot.c;
sparc64_ieee1275 = lib/ieee1275/reboot.c;
mips_arc = lib/mips/arc/reboot.c;
mips_loongson = lib/mips/loongson/reboot.c;
mips_qemu_mips = lib/mips/qemu_mips/reboot.c;
xen = lib/xen/reboot.c;
i386_xen_pvh = lib/xen/reboot.c;
uboot = lib/uboot/reboot.c;
arm_coreboot = lib/dummy/reboot.c;
common = commands/reboot.c;
};
module = {
name = hashsum;
common = commands/hashsum.c;
};
module = {
name = pgp;
common = commands/pgp.c;
cflags = '$(CFLAGS_POSIX)';
cppflags = '-I$(srcdir)/lib/posix_wrap';
};
module = {
name = verifiers;
common = commands/verifiers.c;
};
module = {
name = shim_lock;
common = commands/efi/shim_lock.c;
enable = x86_64_efi;
};
module = {
name = hdparm;
common = commands/hdparm.c;
enable = pci;
enable = mips_qemu_mips;
};
module = {
name = help;
common = commands/help.c;
};
module = {
name = hexdump;
common = commands/hexdump.c;
common = lib/hexdump.c;
};
module = {
name = keystatus;
common = commands/keystatus.c;
};
module = {
name = loadbios;
common = commands/efi/loadbios.c;
enable = i386_efi;
enable = x86_64_efi;
};
module = {
name = loadenv;
common = commands/loadenv.c;
common = lib/envblk.c;
};
module = {
name = ls;
common = commands/ls.c;
};
module = {
name = lsmmap;
common = commands/lsmmap.c;
};
module = {
name = lspci;
common = commands/lspci.c;
enable = pci;
};
module = {
name = memrw;
common = commands/memrw.c;
};
module = {
name = minicmd;
common = commands/minicmd.c;
};
module = {
name = parttool;
common = commands/parttool.c;
};
module = {
name = password;
common = commands/password.c;
};
module = {
name = password_pbkdf2;
common = commands/password_pbkdf2.c;
};
module = {
name = play;
x86 = commands/i386/pc/play.c;
enable = x86;
};
module = {
name = spkmodem;
x86 = term/spkmodem.c;
enable = x86;
};
module = {
name = morse;
x86 = term/morse.c;
enable = x86;
};
module = {
name = probe;
common = commands/probe.c;
};
module = {
name = read;
common = commands/read.c;
};
module = {
name = search;
common = commands/search_wrap.c;
extra_dist = commands/search.c;
};
module = {
name = search_fs_file;
common = commands/search_file.c;
};
module = {
name = search_fs_uuid;
common = commands/search_uuid.c;
};
module = {
name = search_label;
common = commands/search_label.c;
};
module = {
name = setpci;
common = commands/setpci.c;
enable = pci;
};
module = {
name = pcidump;
common = commands/pcidump.c;
enable = pci;
};
module = {
name = sleep;
common = commands/sleep.c;
};
module = {
name = suspend;
ieee1275 = commands/ieee1275/suspend.c;
enable = i386_ieee1275;
enable = powerpc_ieee1275;
};
module = {
name = escc;
ieee1275 = term/ieee1275/escc.c;
enable = powerpc_ieee1275;
};
module = {
name = terminal;
common = commands/terminal.c;
};
module = {
name = test;
common = commands/test.c;
};
module = {
name = true;
common = commands/true.c;
};
module = {
name = usbtest;
common = commands/usbtest.c;
enable = usb;
};
module = {
name = videoinfo;
common = commands/videoinfo.c;
};
module = {
name = videotest;
common = commands/videotest.c;
};
module = {
name = xnu_uuid;
common = commands/xnu_uuid.c;
};
module = {
name = dm_nv;
common = disk/dmraid_nvidia.c;
};
module = {
name = loopback;
common = disk/loopback.c;
};
module = {
name = cryptodisk;
common = disk/cryptodisk.c;
};
module = {
name = luks;
common = disk/luks.c;
common = disk/AFSplitter.c;
};
module = {
name = geli;
common = disk/geli.c;
};
module = {
name = lvm;
common = disk/lvm.c;
};
module = {
name = ldm;
common = disk/ldm.c;
};
module = {
name = mdraid09;
common = disk/mdraid_linux.c;
};
module = {
name = mdraid09_be;
common = disk/mdraid_linux_be.c;
};
module = {
name = mdraid1x;
common = disk/mdraid1x_linux.c;
};
module = {
name = diskfilter;
common = disk/diskfilter.c;
};
module = {
name = raid5rec;
common = disk/raid5_recover.c;
};
module = {
name = raid6rec;
common = disk/raid6_recover.c;
};
module = {
name = scsi;
common = disk/scsi.c;
};
module = {
name = memdisk;
common = disk/memdisk.c;
};
module = {
name = ata;
common = disk/ata.c;
enable = pci;
enable = mips_qemu_mips;
};
module = {
name = ahci;
common = disk/ahci.c;
enable = pci;
};
module = {
name = pata;
common = disk/pata.c;
enable = pci;
enable = mips_qemu_mips;
};
module = {
name = biosdisk;
i386_pc = disk/i386/pc/biosdisk.c;
enable = i386_pc;
};
module = {
name = usbms;
common = disk/usbms.c;
enable = usb;
};
module = {
name = nand;
ieee1275 = disk/ieee1275/nand.c;
enable = i386_ieee1275;
};
module = {
name = efiemu;
common = efiemu/main.c;
common = efiemu/i386/loadcore32.c;
common = efiemu/i386/loadcore64.c;
i386_pc = efiemu/i386/pc/cfgtables.c;
i386_coreboot = efiemu/i386/pc/cfgtables.c;
i386_multiboot = efiemu/i386/pc/cfgtables.c;
i386_ieee1275 = efiemu/i386/nocfgtables.c;
i386_qemu = efiemu/i386/nocfgtables.c;
common = efiemu/mm.c;
common = efiemu/loadcore_common.c;
common = efiemu/symbols.c;
common = efiemu/loadcore32.c;
common = efiemu/loadcore64.c;
common = efiemu/prepare32.c;
common = efiemu/prepare64.c;
common = efiemu/pnvram.c;
common = efiemu/i386/coredetect.c;
extra_dist = efiemu/prepare.c;
extra_dist = efiemu/loadcore.c;
extra_dist = efiemu/runtime/efiemu.S;
extra_dist = efiemu/runtime/efiemu.c;
enable = i386_pc;
enable = i386_coreboot;
enable = i386_ieee1275;
enable = i386_multiboot;
enable = i386_qemu;
};
module = {
name = font;
common = font/font.c;
common = font/font_cmd.c;
enable = videomodules;
};
module = {
name = procfs;
common = fs/proc.c;
};
module = {
name = affs;
common = fs/affs.c;
};
module = {
name = afs;
common = fs/afs.c;
};
module = {
name = bfs;
common = fs/bfs.c;
};
module = {
name = zstd;
common = lib/zstd/debug.c;
common = lib/zstd/entropy_common.c;
common = lib/zstd/error_private.c;
common = lib/zstd/fse_decompress.c;
common = lib/zstd/huf_decompress.c;
common = lib/zstd/module.c;
common = lib/zstd/xxhash.c;
common = lib/zstd/zstd_common.c;
common = lib/zstd/zstd_decompress.c;
cflags = '$(CFLAGS_POSIX) -Wno-undef';
cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/zstd';
};
module = {
name = btrfs;
common = fs/btrfs.c;
common = lib/crc.c;
cflags = '$(CFLAGS_POSIX) -Wno-undef';
cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/minilzo -I$(srcdir)/lib/zstd -DMINILZO_HAVE_CONFIG_H';
};
module = {
name = archelp;
common = fs/archelp.c;
};
module = {
name = cbfs;
common = fs/cbfs.c;
};
module = {
name = cpio;
common = fs/cpio.c;
};
module = {
name = cpio_be;
common = fs/cpio_be.c;
};
module = {
name = newc;
common = fs/newc.c;
};
module = {
name = odc;
common = fs/odc.c;
};
module = {
name = ext2;
common = fs/ext2.c;
};
module = {
name = fat;
common = fs/fat.c;
};
module = {
name = exfat;
common = fs/exfat.c;
};
module = {
name = f2fs;
common = fs/f2fs.c;
};
module = {
name = fshelp;
common = fs/fshelp.c;
};
module = {
name = hfs;
common = fs/hfs.c;
};
module = {
name = hfsplus;
common = fs/hfsplus.c;
};
module = {
name = hfspluscomp;
common = fs/hfspluscomp.c;
};
module = {
name = iso9660;
common = fs/iso9660.c;
};
module = {
name = jfs;
common = fs/jfs.c;
};
module = {
name = minix;
common = fs/minix.c;
};
module = {
name = minix2;
common = fs/minix2.c;
};
module = {
name = minix3;
common = fs/minix3.c;
};
module = {
name = minix_be;
common = fs/minix_be.c;
};
module = {
name = minix2_be;
common = fs/minix2_be.c;
};
module = {
name = minix3_be;
common = fs/minix3_be.c;
};
module = {
name = nilfs2;
common = fs/nilfs2.c;
};
module = {
name = ntfs;
common = fs/ntfs.c;
};
module = {
name = ntfscomp;
common = fs/ntfscomp.c;
};
module = {
name = reiserfs;
common = fs/reiserfs.c;
};
module = {
name = romfs;
common = fs/romfs.c;
};
module = {
name = sfs;
common = fs/sfs.c;
};
module = {
name = squash4;
common = fs/squash4.c;
cflags = '$(CFLAGS_POSIX) -Wno-undef';
cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed -I$(srcdir)/lib/minilzo -DMINILZO_HAVE_CONFIG_H';
};
module = {
name = tar;
common = fs/tar.c;
};
module = {
name = udf;
common = fs/udf.c;
};
module = {
name = ufs1;
common = fs/ufs.c;
};
module = {
name = ufs1_be;
common = fs/ufs_be.c;
};
module = {
name = ufs2;
common = fs/ufs2.c;
};
module = {
name = xfs;
common = fs/xfs.c;
};
module = {
name = zfs;
common = fs/zfs/zfs.c;
common = fs/zfs/zfs_lzjb.c;
common = fs/zfs/zfs_lz4.c;
common = fs/zfs/zfs_sha256.c;
common = fs/zfs/zfs_fletcher.c;
};
module = {
name = zfscrypt;
common = fs/zfs/zfscrypt.c;
};
module = {
name = zfsinfo;
common = fs/zfs/zfsinfo.c;
};
module = {
name = macbless;
common = commands/macbless.c;
};
module = {
name = pxe;
i386_pc = net/drivers/i386/pc/pxe.c;
enable = i386_pc;
};
module = {
name = gettext;
common = gettext/gettext.c;
};
module = {
name = gfxmenu;
common = gfxmenu/gfxmenu.c;
common = gfxmenu/view.c;
common = gfxmenu/font.c;
common = gfxmenu/icon_manager.c;
common = gfxmenu/theme_loader.c;
common = gfxmenu/widget-box.c;
common = gfxmenu/gui_canvas.c;
common = gfxmenu/gui_circular_progress.c;
common = gfxmenu/gui_box.c;
common = gfxmenu/gui_label.c;
common = gfxmenu/gui_list.c;
common = gfxmenu/gui_image.c;
common = gfxmenu/gui_progress_bar.c;
common = gfxmenu/gui_util.c;
common = gfxmenu/gui_string_util.c;
};
/* Added by longpanda for Ventoy Project */
module = {
name = ventoy;
common = ventoy/ventoy.c;
common = ventoy/ventoy_linux.c;
common = ventoy/ventoy_windows.c;
common = ventoy/ventoy_plugin.c;
common = ventoy/ventoy_json.c;
common = ventoy/lzx.c;
common = ventoy/huffman.c;
};
module = {
name = hello;
common = hello/hello.c;
};
module = {
name = gzio;
common = io/gzio.c;
};
module = {
name = offsetio;
common = io/offset.c;
};
module = {
name = bufio;
common = io/bufio.c;
enable = videomodules;
};
module = {
name = elf;
common = kern/elf.c;
extra_dist = kern/elfXX.c;
};
module = {
name = crypto;
common = lib/crypto.c;
extra_dist = lib/libgcrypt-grub/cipher/crypto.lst;
};
module = {
name = pbkdf2;
common = lib/pbkdf2.c;
};
module = {
name = relocator;
common = lib/relocator.c;
x86 = lib/i386/relocator16.S;
x86 = lib/i386/relocator32.S;
x86 = lib/i386/relocator64.S;
i386_xen_pvh = lib/i386/relocator16.S;
i386_xen_pvh = lib/i386/relocator32.S;
i386_xen_pvh = lib/i386/relocator64.S;
i386 = lib/i386/relocator_asm.S;
i386_xen_pvh = lib/i386/relocator_asm.S;
x86_64 = lib/x86_64/relocator_asm.S;
i386_xen = lib/i386/relocator_asm.S;
x86_64_xen = lib/x86_64/relocator_asm.S;
x86 = lib/i386/relocator.c;
x86 = lib/i386/relocator_common_c.c;
i386_xen_pvh = lib/i386/relocator.c;
i386_xen_pvh = lib/i386/relocator_common_c.c;
ieee1275 = lib/ieee1275/relocator.c;
efi = lib/efi/relocator.c;
mips = lib/mips/relocator_asm.S;
mips = lib/mips/relocator.c;
powerpc = lib/powerpc/relocator_asm.S;
powerpc = lib/powerpc/relocator.c;
xen = lib/xen/relocator.c;
i386_xen = lib/i386/xen/relocator.S;
x86_64_xen = lib/x86_64/xen/relocator.S;
xen = lib/i386/relocator_common_c.c;
x86_64_efi = lib/x86_64/efi/relocator.c;
extra_dist = lib/i386/relocator_common.S;
extra_dist = kern/powerpc/cache_flush.S;
enable = mips;
enable = powerpc;
enable = x86;
enable = i386_xen_pvh;
enable = xen;
};
module = {
name = datetime;
cmos = lib/cmos_datetime.c;
efi = lib/efi/datetime.c;
uboot = lib/dummy/datetime.c;
arm_coreboot = lib/dummy/datetime.c;
sparc64_ieee1275 = lib/ieee1275/datetime.c;
powerpc_ieee1275 = lib/ieee1275/datetime.c;
sparc64_ieee1275 = lib/ieee1275/cmos.c;
powerpc_ieee1275 = lib/ieee1275/cmos.c;
xen = lib/xen/datetime.c;
i386_xen_pvh = lib/xen/datetime.c;
mips_arc = lib/arc/datetime.c;
enable = noemu;
};
module = {
name = setjmp;
common = lib/setjmp.S;
extra_dist = lib/i386/setjmp.S;
extra_dist = lib/mips/setjmp.S;
extra_dist = lib/x86_64/setjmp.S;
extra_dist = lib/sparc64/setjmp.S;
extra_dist = lib/powerpc/setjmp.S;
extra_dist = lib/ia64/setjmp.S;
extra_dist = lib/ia64/longjmp.S;
extra_dist = lib/arm/setjmp.S;
extra_dist = lib/arm64/setjmp.S;
extra_dist = lib/riscv/setjmp.S;
};
module = {
name = aout;
common = loader/aout.c;
enable = x86;
};
module = {
name = bsd;
x86 = loader/i386/bsd.c;
x86 = loader/i386/bsd32.c;
x86 = loader/i386/bsd64.c;
extra_dist = loader/i386/bsdXX.c;
extra_dist = loader/i386/bsd_pagetable.c;
enable = x86;
};
module = {
name = plan9;
i386_pc = loader/i386/pc/plan9.c;
enable = i386_pc;
};
module = {
name = linux16;
common = loader/i386/pc/linux.c;
enable = x86;
};
module = {
name = ntldr;
i386_pc = loader/i386/pc/ntldr.c;
enable = i386_pc;
};
module = {
name = truecrypt;
i386_pc = loader/i386/pc/truecrypt.c;
enable = i386_pc;
};
module = {
name = freedos;
i386_pc = loader/i386/pc/freedos.c;
enable = i386_pc;
};
module = {
name = pxechain;
i386_pc = loader/i386/pc/pxechainloader.c;
enable = i386_pc;
};
module = {
name = multiboot2;
cppflags = "-DGRUB_USE_MULTIBOOT2";
common = loader/multiboot.c;
common = loader/multiboot_mbi2.c;
enable = x86;
enable = i386_xen_pvh;
enable = mips;
};
module = {
name = multiboot;
common = loader/multiboot.c;
x86 = loader/i386/multiboot_mbi.c;
i386_xen_pvh = loader/i386/multiboot_mbi.c;
extra_dist = loader/multiboot_elfxx.c;
enable = x86;
enable = i386_xen_pvh;
};
module = {
name = xen_boot;
arm64 = loader/arm64/xen_boot.c;
enable = arm64;
};
module = {
name = linux;
x86 = loader/i386/linux.c;
i386_xen_pvh = loader/i386/linux.c;
xen = loader/i386/xen.c;
i386_pc = lib/i386/pc/vesa_modes_table.c;
i386_xen_pvh = lib/i386/pc/vesa_modes_table.c;
mips = loader/mips/linux.c;
powerpc_ieee1275 = loader/powerpc/ieee1275/linux.c;
sparc64_ieee1275 = loader/sparc64/ieee1275/linux.c;
ia64_efi = loader/ia64/efi/linux.c;
arm_coreboot = loader/arm/linux.c;
arm_efi = loader/arm64/linux.c;
arm_uboot = loader/arm/linux.c;
arm64 = loader/arm64/linux.c;
riscv32 = loader/riscv/linux.c;
riscv64 = loader/riscv/linux.c;
common = loader/linux.c;
common = lib/cmdline.c;
enable = noemu;
};
module = {
name = fdt;
efi = loader/efi/fdt.c;
common = lib/fdt.c;
enable = fdt;
};
module = {
name = xnu;
x86 = loader/xnu_resume.c;
x86 = loader/i386/xnu.c;
x86 = loader/xnu.c;
/* Code is pretty generic but relies on RNG which
is available only on few platforms. It's not a
big deal as xnu needs ACPI anyway and we have
RNG on all platforms with ACPI.
*/
enable = i386_multiboot;
enable = i386_coreboot;
enable = i386_pc;
enable = i386_efi;
enable = x86_64_efi;
};
module = {
name = random;
x86 = lib/i386/random.c;
common = lib/random.c;
i386_multiboot = kern/i386/tsc_pmtimer.c;
i386_coreboot = kern/i386/tsc_pmtimer.c;
i386_pc = kern/i386/tsc_pmtimer.c;
enable = i386_multiboot;
enable = i386_coreboot;
enable = i386_pc;
enable = i386_efi;
enable = x86_64_efi;
};
module = {
name = macho;
common = loader/macho.c;
common = loader/macho32.c;
common = loader/macho64.c;
common = loader/lzss.c;
extra_dist = loader/machoXX.c;
};
module = {
name = appleldr;
common = loader/efi/appleloader.c;
enable = i386_efi;
enable = x86_64_efi;
};
module = {
name = chain;
efi = loader/efi/chainloader.c;
i386_pc = loader/i386/pc/chainloader.c;
i386_coreboot = loader/i386/coreboot/chainloader.c;
i386_coreboot = lib/LzmaDec.c;
enable = i386_pc;
enable = i386_coreboot;
enable = efi;
};
module = {
name = mmap;
common = mmap/mmap.c;
x86 = mmap/i386/uppermem.c;
x86 = mmap/i386/mmap.c;
i386_xen_pvh = mmap/i386/uppermem.c;
i386_xen_pvh = mmap/i386/mmap.c;
i386_pc = mmap/i386/pc/mmap.c;
i386_pc = mmap/i386/pc/mmap_helper.S;
efi = mmap/efi/mmap.c;
mips = mmap/mips/uppermem.c;
enable = x86;
enable = i386_xen_pvh;
enable = ia64_efi;
enable = arm_efi;
enable = arm64_efi;
enable = riscv32_efi;
enable = riscv64_efi;
enable = mips;
};
module = {
name = normal;
common = normal/main.c;
common = normal/cmdline.c;
common = normal/dyncmd.c;
common = normal/auth.c;
common = normal/autofs.c;
common = normal/color.c;
common = normal/completion.c;
common = normal/datetime.c;
common = normal/menu.c;
common = normal/menu_entry.c;
common = normal/menu_text.c;
common = normal/misc.c;
common = normal/crypto.c;
common = normal/term.c;
common = normal/context.c;
common = normal/charset.c;
common = lib/getline.c;
common = script/main.c;
common = script/script.c;
common = script/execute.c;
common = script/function.c;
common = script/lexer.c;
common = script/argv.c;
common = commands/menuentry.c;
common = unidata.c;
common_nodist = grub_script.tab.c;
common_nodist = grub_script.yy.c;
common_nodist = grub_script.tab.h;
common_nodist = grub_script.yy.h;
extra_dist = script/yylex.l;
extra_dist = script/parser.y;
cflags = '$(CFLAGS_POSIX) -Wno-redundant-decls';
cppflags = '$(CPPFLAGS_POSIX)';
};
module = {
name = part_acorn;
common = partmap/acorn.c;
};
module = {
name = part_amiga;
common = partmap/amiga.c;
};
module = {
name = part_apple;
common = partmap/apple.c;
};
module = {
name = part_gpt;
common = partmap/gpt.c;
};
module = {
name = part_msdos;
common = partmap/msdos.c;
};
module = {
name = part_sun;
common = partmap/sun.c;
};
module = {
name = part_plan;
common = partmap/plan.c;
};
module = {
name = part_dvh;
common = partmap/dvh.c;
};
module = {
name = part_bsd;
common = partmap/bsdlabel.c;
};
module = {
name = part_sunpc;
common = partmap/sunpc.c;
};
module = {
name = part_dfly;
common = partmap/dfly.c;
};
module = {
name = msdospart;
common = parttool/msdospart.c;
};
module = {
name = at_keyboard;
common = term/at_keyboard.c;
common = term/ps2.c;
enable = x86;
};
module = {
name = gfxterm;
common = term/gfxterm.c;
enable = videomodules;
};
module = {
name = gfxterm_background;
common = term/gfxterm_background.c;
};
module = {
name = serial;
common = term/serial.c;
x86 = term/ns8250.c;
ieee1275 = term/ieee1275/serial.c;
mips_arc = term/arc/serial.c;
efi = term/efi/serial.c;
enable = terminfomodule;
enable = ieee1275;
enable = mips_arc;
};
module = {
name = sendkey;
i386_pc = commands/i386/pc/sendkey.c;
enable = i386_pc;
};
module = {
name = terminfo;
common = term/terminfo.c;
common = term/tparm.c;
enable = terminfomodule;
};
module = {
name = usb_keyboard;
common = term/usb_keyboard.c;
enable = usb;
};
module = {
name = vga;
common = video/i386/pc/vga.c;
enable = i386_pc;
};
module = {
name = vga_text;
common = term/i386/pc/vga_text.c;
enable = i386_pc;
};
module = {
name = mda_text;
common = term/i386/pc/mda_text.c;
enable = i386_pc;
enable = i386_coreboot_multiboot_qemu;
};
module = {
name = video_cirrus;
x86 = video/cirrus.c;
enable = x86;
};
module = {
name = video_bochs;
x86 = video/bochs.c;
enable = x86;
};
module = {
name = functional_test;
common = tests/lib/functional_test.c;
common = tests/lib/test.c;
common = tests/checksums.h;
common = tests/video_checksum.c;
common = tests/fake_input.c;
common = video/capture.c;
};
module = {
name = exfctest;
common = tests/example_functional_test.c;
};
module = {
name = strtoull_test;
common = tests/strtoull_test.c;
};
module = {
name = setjmp_test;
common = tests/setjmp_test.c;
};
module = {
name = signature_test;
common = tests/signature_test.c;
common = tests/signatures.h;
};
module = {
name = sleep_test;
common = tests/sleep_test.c;
};
module = {
name = xnu_uuid_test;
common = tests/xnu_uuid_test.c;
};
module = {
name = pbkdf2_test;
common = tests/pbkdf2_test.c;
};
module = {
name = legacy_password_test;
common = tests/legacy_password_test.c;
enable = i386_pc;
enable = i386_xen_pvh;
enable = i386_efi;
enable = x86_64_efi;
enable = emu;
enable = xen;
};
module = {
name = div;
common = lib/division.c;
enable = no_softdiv;
};
module = {
name = div_test;
common = tests/div_test.c;
};
module = {
name = mul_test;
common = tests/mul_test.c;
};
module = {
name = shift_test;
common = tests/shift_test.c;
};
module = {
name = cmp_test;
common = tests/cmp_test.c;
};
module = {
name = ctz_test;
common = tests/ctz_test.c;
};
module = {
name = bswap_test;
common = tests/bswap_test.c;
};
module = {
name = videotest_checksum;
common = tests/videotest_checksum.c;
};
module = {
name = gfxterm_menu;
common = tests/gfxterm_menu.c;
};
module = {
name = cmdline_cat_test;
common = tests/cmdline_cat_test.c;
};
module = {
name = bitmap;
common = video/bitmap.c;
};
module = {
name = bitmap_scale;
common = video/bitmap_scale.c;
};
module = {
name = efi_gop;
efi = video/efi_gop.c;
enable = efi;
};
module = {
name = efi_uga;
efi = video/efi_uga.c;
enable = i386_efi;
enable = x86_64_efi;
};
module = {
name = jpeg;
common = video/readers/jpeg.c;
};
module = {
name = png;
common = video/readers/png.c;
};
module = {
name = tga;
common = video/readers/tga.c;
};
module = {
name = vbe;
common = video/i386/pc/vbe.c;
enable = i386_pc;
};
module = {
name = video_fb;
common = video/fb/video_fb.c;
common = video/fb/fbblit.c;
common = video/fb/fbfill.c;
common = video/fb/fbutil.c;
enable = videomodules;
};
module = {
name = video;
common = video/video.c;
enable = videomodules;
};
module = {
name = video_colors;
common = video/colors.c;
};
module = {
name = ieee1275_fb;
ieee1275 = video/ieee1275.c;
enable = powerpc_ieee1275;
};
module = {
name = sdl;
emu = video/emu/sdl.c;
enable = emu;
condition = COND_GRUB_EMU_SDL;
};
module = {
name = datehook;
common = hook/datehook.c;
};
module = {
name = net;
common = net/net.c;
common = net/dns.c;
common = net/bootp.c;
common = net/ip.c;
common = net/udp.c;
common = net/tcp.c;
common = net/icmp.c;
common = net/icmp6.c;
common = net/ethernet.c;
common = net/arp.c;
common = net/netbuff.c;
};
module = {
name = tftp;
common = net/tftp.c;
};
module = {
name = http;
common = net/http.c;
};
module = {
name = ofnet;
common = net/drivers/ieee1275/ofnet.c;
enable = ieee1275;
};
module = {
name = ubootnet;
common = net/drivers/uboot/ubootnet.c;
enable = uboot;
};
module = {
name = efinet;
common = net/drivers/efi/efinet.c;
enable = efi;
};
module = {
name = emunet;
emu = net/drivers/emu/emunet.c;
enable = emu;
};
module = {
name = legacycfg;
common = commands/legacycfg.c;
common = lib/legacy_parse.c;
emu = lib/i386/pc/vesa_modes_table.c;
i386_efi = lib/i386/pc/vesa_modes_table.c;
x86_64_efi = lib/i386/pc/vesa_modes_table.c;
xen = lib/i386/pc/vesa_modes_table.c;
enable = i386_pc;
enable = i386_xen_pvh;
enable = i386_efi;
enable = x86_64_efi;
enable = emu;
enable = xen;
};
module = {
name = syslinuxcfg;
common = lib/syslinux_parse.c;
common = commands/syslinuxcfg.c;
};
module = {
name = test_blockarg;
common = tests/test_blockarg.c;
};
module = {
name = xzio;
common = io/xzio.c;
common = lib/xzembed/xz_dec_bcj.c;
common = lib/xzembed/xz_dec_lzma2.c;
common = lib/xzembed/xz_dec_stream.c;
cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed';
cflags='-Wno-unreachable-code';
};
module = {
name = lzopio;
common = io/lzopio.c;
common = lib/minilzo/minilzo.c;
cflags = '$(CFLAGS_POSIX) -Wno-undef -Wno-redundant-decls -Wno-error';
cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/minilzo -DMINILZO_HAVE_CONFIG_H';
};
module = {
name = testload;
common = commands/testload.c;
};
module = {
name = backtrace;
x86 = lib/i386/backtrace.c;
i386_xen_pvh = lib/i386/backtrace.c;
i386_xen = lib/i386/backtrace.c;
x86_64_xen = lib/i386/backtrace.c;
common = lib/backtrace.c;
enable = x86;
enable = i386_xen_pvh;
enable = i386_xen;
enable = x86_64_xen;
};
module = {
name = lsapm;
common = commands/i386/pc/lsapm.c;
enable = i386_pc;
};
module = {
name = keylayouts;
common = commands/keylayouts.c;
enable = x86;
};
module = {
name = priority_queue;
common = lib/priority_queue.c;
};
module = {
name = time;
common = commands/time.c;
};
module = {
name = cacheinfo;
common = commands/cacheinfo.c;
condition = COND_ENABLE_CACHE_STATS;
};
module = {
name = boottime;
common = commands/boottime.c;
condition = COND_ENABLE_BOOT_TIME_STATS;
};
module = {
name = adler32;
common = lib/adler32.c;
};
module = {
name = crc64;
common = lib/crc64.c;
};
module = {
name = mpi;
common = lib/libgcrypt-grub/mpi/mpiutil.c;
common = lib/libgcrypt-grub/mpi/mpi-bit.c;
common = lib/libgcrypt-grub/mpi/mpi-add.c;
common = lib/libgcrypt-grub/mpi/mpi-mul.c;
common = lib/libgcrypt-grub/mpi/mpi-mod.c;
common = lib/libgcrypt-grub/mpi/mpi-gcd.c;
common = lib/libgcrypt-grub/mpi/mpi-div.c;
common = lib/libgcrypt-grub/mpi/mpi-cmp.c;
common = lib/libgcrypt-grub/mpi/mpi-inv.c;
common = lib/libgcrypt-grub/mpi/mpi-pow.c;
common = lib/libgcrypt-grub/mpi/mpi-mpow.c;
common = lib/libgcrypt-grub/mpi/mpih-lshift.c;
common = lib/libgcrypt-grub/mpi/mpih-mul.c;
common = lib/libgcrypt-grub/mpi/mpih-mul1.c;
common = lib/libgcrypt-grub/mpi/mpih-mul2.c;
common = lib/libgcrypt-grub/mpi/mpih-mul3.c;
common = lib/libgcrypt-grub/mpi/mpih-add1.c;
common = lib/libgcrypt-grub/mpi/mpih-sub1.c;
common = lib/libgcrypt-grub/mpi/mpih-div.c;
common = lib/libgcrypt-grub/mpi/mpicoder.c;
common = lib/libgcrypt-grub/mpi/mpih-rshift.c;
common = lib/libgcrypt-grub/mpi/mpi-inline.c;
common = lib/libgcrypt_wrap/mem.c;
cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls -Wno-sign-compare';
cppflags = '$(CPPFLAGS_GCRY)';
};
module = {
name = all_video;
common = lib/fake_module.c;
};
module = {
name = gdb;
common = gdb/cstub.c;
common = gdb/gdb.c;
i386 = gdb/i386/idt.c;
i386 = gdb/i386/machdep.S;
i386 = gdb/i386/signal.c;
enable = i386;
};
module = {
name = testspeed;
common = commands/testspeed.c;
};
module = {
name = tpm;
common = commands/tpm.c;
efi = commands/efi/tpm.c;
enable = x86_64_efi;
};
module = {
name = tr;
common = commands/tr.c;
};
module = {
name = progress;
common = lib/progress.c;
};
module = {
name = file;
common = commands/file.c;
common = commands/file32.c;
common = commands/file64.c;
extra_dist = commands/fileXX.c;
common = loader/i386/xen_file.c;
common = loader/i386/xen_file32.c;
common = loader/i386/xen_file64.c;
extra_dist = loader/i386/xen_fileXX.c;
};
module = {
name = rdmsr;
common = commands/i386/rdmsr.c;
enable = x86;
};
module = {
name = wrmsr;
common = commands/i386/wrmsr.c;
enable = x86;
};
/* -*-Asm-*- */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,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/>.
*/
#include <grub/symbol.h>
#include <grub/machine/boot.h>
/*
* defines for the code go here
*/
/* Print message string */
#define MSG(x) movw $x, %si; call LOCAL(message)
#define ERR(x) movw $x, %si; jmp LOCAL(error_message)
.macro floppy
part_start:
LOCAL(probe_values):
.byte 36, 18, 15, 9, 0
LOCAL(floppy_probe):
pushw %dx
/*
* Perform floppy probe.
*/
#ifdef __APPLE__
LOCAL(probe_values_minus_one) = LOCAL(probe_values) - 1
movw MACRO_DOLLAR(LOCAL(probe_values_minus_one)), %si
#else
movw MACRO_DOLLAR(LOCAL(probe_values)) - 1, %si
#endif
LOCAL(probe_loop):
/* reset floppy controller INT 13h AH=0 */
xorw %ax, %ax
int MACRO_DOLLAR(0x13)
incw %si
movb (%si), %cl
/* if number of sectors is 0, display error and die */
testb %cl, %cl
jnz 1f
/*
* Floppy disk probe failure.
*/
MSG(fd_probe_error_string)
jmp LOCAL(general_error)
/* "Floppy" */
fd_probe_error_string: .asciz "Floppy"
1:
/* perform read */
movw MACRO_DOLLAR(GRUB_BOOT_MACHINE_BUFFER_SEG), %bx
movw %bx, %es
xorw %bx, %bx
movw MACRO_DOLLAR(0x201), %ax
movb MACRO_DOLLAR(0), %ch
movb MACRO_DOLLAR(0), %dh
int MACRO_DOLLAR(0x13)
/* if error, jump to "LOCAL(probe_loop)" */
jc LOCAL(probe_loop)
/* %cl is already the correct value! */
movb MACRO_DOLLAR(1), %dh
movb MACRO_DOLLAR(79), %ch
jmp LOCAL(final_init)
.endm
.macro scratch
/* scratch space */
mode:
.byte 0
disk_address_packet:
sectors:
.long 0
heads:
.long 0
cylinders:
.word 0
sector_start:
.byte 0
head_start:
.byte 0
cylinder_start:
.word 0
/* more space... */
.endm
.file "boot.S"
.text
/* Tell GAS to generate 16-bit instructions so that this code works
in real mode. */
.code16
.globl _start, start;
_start:
start:
/*
* _start is loaded at 0x7c00 and is jumped to with CS:IP 0:0x7c00
*/
/*
* Beginning of the sector is compatible with the FAT/HPFS BIOS
* parameter block.
*/
jmp LOCAL(after_BPB)
nop /* do I care about this ??? */
#ifdef HYBRID_BOOT
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
jmp LOCAL(after_BPB)
#else
/*
* This space is for the BIOS parameter block!!!! Don't change
* the first jump, nor start the code anywhere but right after
* this area.
*/
.org GRUB_BOOT_MACHINE_BPB_START
.org 4
#endif
#ifdef HYBRID_BOOT
floppy
#else
scratch
#endif
.org GRUB_BOOT_MACHINE_BPB_END
/*
* End of BIOS parameter block.
*/
LOCAL(kernel_address):
.word GRUB_BOOT_MACHINE_KERNEL_ADDR
#ifndef HYBRID_BOOT
.org GRUB_BOOT_MACHINE_KERNEL_SECTOR
LOCAL(kernel_sector):
.long 1
LOCAL(kernel_sector_high):
.long 0
#endif
.org GRUB_BOOT_MACHINE_BOOT_DRIVE
boot_drive:
.byte 0xff /* the disk to load kernel from */
/* 0xff means use the boot drive */
LOCAL(after_BPB):
/* general setup */
cli /* we're not safe here! */
/*
* This is a workaround for buggy BIOSes which don't pass boot
* drive correctly. If GRUB is installed into a HDD, check if
* DL is masked correctly. If not, assume that the BIOS passed
* a bogus value and set DL to 0x80, since this is the only
* possible boot drive. If GRUB is installed into a floppy,
* this does nothing (only jump).
*/
.org GRUB_BOOT_MACHINE_DRIVE_CHECK
boot_drive_check:
jmp 3f /* grub-setup may overwrite this jump */
testb $0x80, %dl
jz 2f
3:
/* Ignore %dl different from 0-0x0f and 0x80-0x8f. */
testb $0x70, %dl
jz 1f
2:
movb $0x80, %dl
1:
/*
* ljmp to the next instruction because some bogus BIOSes
* jump to 07C0:0000 instead of 0000:7C00.
*/
ljmp $0, $real_start
real_start:
/* set up %ds and %ss as offset from 0 */
xorw %ax, %ax
movw %ax, %ds
movw %ax, %ss
/* set up the REAL stack */
movw $GRUB_BOOT_MACHINE_STACK_SEG, %sp
sti /* we're safe again */
/*
* Check if we have a forced disk reference here
*/
movb boot_drive, %al
cmpb $0xff, %al
je 1f
movb %al, %dl
1:
/* save drive reference first thing! */
pushw %dx
/* print a notification message on the screen */
MSG(notification_string)
/* set %si to the disk address packet */
movw $disk_address_packet, %si
/* check if LBA is supported */
movb $0x41, %ah
movw $0x55aa, %bx
int $0x13
/*
* %dl may have been clobbered by INT 13, AH=41H.
* This happens, for example, with AST BIOS 1.04.
*/
popw %dx
pushw %dx
/* use CHS if fails */
jc LOCAL(chs_mode)
cmpw $0xaa55, %bx
jne LOCAL(chs_mode)
andw $1, %cx
jz LOCAL(chs_mode)
LOCAL(lba_mode):
xorw %ax, %ax
movw %ax, 4(%si)
incw %ax
/* set the mode to non-zero */
movb %al, -1(%si)
/* the blocks */
movw %ax, 2(%si)
/* the size and the reserved byte */
movw $0x0010, (%si)
/* the absolute address */
movl LOCAL(kernel_sector), %ebx
movl %ebx, 8(%si)
movl LOCAL(kernel_sector_high), %ebx
movl %ebx, 12(%si)
/* the segment of buffer address */
movw $GRUB_BOOT_MACHINE_BUFFER_SEG, 6(%si)
/*
* BIOS call "INT 0x13 Function 0x42" to read sectors from disk into memory
* Call with %ah = 0x42
* %dl = drive number
* %ds:%si = segment:offset of disk address packet
* Return:
* %al = 0x0 on success; err code on failure
*/
movb $0x42, %ah
int $0x13
/* LBA read is not supported, so fallback to CHS. */
jc LOCAL(chs_mode)
movw $GRUB_BOOT_MACHINE_BUFFER_SEG, %bx
jmp LOCAL(copy_buffer)
LOCAL(chs_mode):
/*
* Determine the hard disk geometry from the BIOS!
* We do this first, so that LS-120 IDE floppies work correctly.
*/
movb $8, %ah
int $0x13
jnc LOCAL(final_init)
popw %dx
/*
* The call failed, so maybe use the floppy probe instead.
*/
testb %dl, %dl
jnb LOCAL(floppy_probe)
/* Nope, we definitely have a hard disk, and we're screwed. */
ERR(hd_probe_error_string)
LOCAL(final_init):
/* set the mode to zero */
movzbl %dh, %eax
movb %ah, -1(%si)
/* save number of heads */
incw %ax
movl %eax, 4(%si)
movzbw %cl, %dx
shlw $2, %dx
movb %ch, %al
movb %dh, %ah
/* save number of cylinders */
incw %ax
movw %ax, 8(%si)
movzbw %dl, %ax
shrb $2, %al
/* save number of sectors */
movl %eax, (%si)
setup_sectors:
/* load logical sector start (top half) */
movl LOCAL(kernel_sector_high), %eax
orl %eax, %eax
jnz LOCAL(geometry_error)
/* load logical sector start (bottom half) */
movl LOCAL(kernel_sector), %eax
/* zero %edx */
xorl %edx, %edx
/* divide by number of sectors */
divl (%si)
/* save sector start */
movb %dl, %cl
xorw %dx, %dx /* zero %edx */
divl 4(%si) /* divide by number of heads */
/* do we need too many cylinders? */
cmpw 8(%si), %ax
jge LOCAL(geometry_error)
/* normalize sector start (1-based) */
incb %cl
/* low bits of cylinder start */
movb %al, %ch
/* high bits of cylinder start */
xorb %al, %al
shrw $2, %ax
orb %al, %cl
/* save head start */
movb %dl, %al
/* restore %dl */
popw %dx
/* head start */
movb %al, %dh
/*
* BIOS call "INT 0x13 Function 0x2" to read sectors from disk into memory
* Call with %ah = 0x2
* %al = number of sectors
* %ch = cylinder
* %cl = sector (bits 6-7 are high bits of "cylinder")
* %dh = head
* %dl = drive (0x80 for hard disk, 0x0 for floppy disk)
* %es:%bx = segment:offset of buffer
* Return:
* %al = 0x0 on success; err code on failure
*/
movw $GRUB_BOOT_MACHINE_BUFFER_SEG, %bx
movw %bx, %es /* load %es segment with disk buffer */
xorw %bx, %bx /* %bx = 0, put it at 0 in the segment */
movw $0x0201, %ax /* function 2 */
int $0x13
jc LOCAL(read_error)
movw %es, %bx
LOCAL(copy_buffer):
/*
* We need to save %cx and %si because the startup code in
* kernel uses them without initializing them.
*/
pusha
pushw %ds
movw $0x100, %cx
movw %bx, %ds
xorw %si, %si
movw $GRUB_BOOT_MACHINE_KERNEL_ADDR, %di
movw %si, %es
cld
rep
movsw
popw %ds
popa
/* boot kernel */
jmp *(LOCAL(kernel_address))
/* END OF MAIN LOOP */
/*
* BIOS Geometry translation error (past the end of the disk geometry!).
*/
LOCAL(geometry_error):
ERR(geometry_error_string)
/*
* Read error on the disk.
*/
LOCAL(read_error):
movw $read_error_string, %si
LOCAL(error_message):
call LOCAL(message)
LOCAL(general_error):
MSG(general_error_string)
/* go here when you need to stop the machine hard after an error condition */
/* tell the BIOS a boot failure, which may result in no effect */
int $0x18
LOCAL(stop):
jmp LOCAL(stop)
ventoy_uuid: .ascii "XXXXXXXXXXXXXXXX"
notification_string: .asciz "GR"
geometry_error_string: .asciz "Ge"
hd_probe_error_string: .asciz "HD"
read_error_string: .asciz "Rd"
general_error_string: .asciz " Er\r\n"
/*
* message: write the string pointed to by %si
*
* WARNING: trashes %si, %ax, and %bx
*/
/*
* Use BIOS "int 10H Function 0Eh" to write character in teletype mode
* %ah = 0xe %al = character
* %bh = page %bl = foreground color (graphics modes)
*/
1:
movw $0x0001, %bx
movb $0xe, %ah
int $0x10 /* display a byte */
LOCAL(message):
lodsb
cmpb $0, %al
jne 1b /* if not end of string, jmp to display */
ret
/*
* Windows NT breaks compatibility by embedding a magic
* number here.
*/
#ifdef HYBRID_BOOT
.org 0x1b0
LOCAL(kernel_sector):
.long 1
LOCAL(kernel_sector_high):
.long 0
#endif
.org GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC
nt_magic:
.long 0
.word 0
/*
* This is where an MBR would go if on a hard disk. The code
* here isn't even referenced unless we're on a floppy. Kinda
* sneaky, huh?
*/
.org GRUB_BOOT_MACHINE_PART_START
#ifndef HYBRID_BOOT
floppy
#else
scratch
#endif
.org GRUB_BOOT_MACHINE_PART_END
/* the last 2 bytes in the sector 0 contain the signature */
.word GRUB_BOOT_MACHINE_SIGNATURE
/* blocklist.c - print the block list of a file */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2006,2007 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/dl.h>
#include <grub/misc.h>
#include <grub/file.h>
#include <grub/mm.h>
#include <grub/disk.h>
#include <grub/partition.h>
#include <grub/command.h>
#include <grub/i18n.h>
GRUB_MOD_LICENSE ("GPLv3+");
/* Context for grub_cmd_blocklist. */
struct blocklist_ctx
{
unsigned long start_sector;
unsigned num_sectors;
int num_entries;
grub_disk_addr_t part_start;
};
/* Helper for grub_cmd_blocklist. */
static void
print_blocklist (grub_disk_addr_t sector, unsigned num,
unsigned offset, unsigned length, struct blocklist_ctx *ctx)
{
if (ctx->num_entries++)
grub_printf (",");
grub_printf ("%llu", (unsigned long long) (sector - ctx->part_start));
if (num > 0)
grub_printf ("+%u", num);
if (offset != 0 || length != 0)
grub_printf ("[%u-%u]", offset, offset + length);
}
/* Helper for grub_cmd_blocklist. */
static void
read_blocklist (grub_disk_addr_t sector, unsigned offset, unsigned length,
void *data)
{
struct blocklist_ctx *ctx = data;
if (ctx->num_sectors > 0)
{
if (ctx->start_sector + ctx->num_sectors == sector
&& offset == 0 && length >= GRUB_DISK_SECTOR_SIZE)
{
ctx->num_sectors += length >> GRUB_DISK_SECTOR_BITS;
sector += length >> GRUB_DISK_SECTOR_BITS;
length &= (GRUB_DISK_SECTOR_SIZE - 1);
}
if (!length)
return;
print_blocklist (ctx->start_sector, ctx->num_sectors, 0, 0, ctx);
ctx->num_sectors = 0;
}
if (offset)
{
unsigned l = length + offset;
l &= (GRUB_DISK_SECTOR_SIZE - 1);
l -= offset;
print_blocklist (sector, 0, offset, l, ctx);
length -= l;
sector++;
offset = 0;
}
if (!length)
return;
if (length & (GRUB_DISK_SECTOR_SIZE - 1))
{
if (length >> GRUB_DISK_SECTOR_BITS)
{
print_blocklist (sector, length >> GRUB_DISK_SECTOR_BITS, 0, 0, ctx);
sector += length >> GRUB_DISK_SECTOR_BITS;
}
print_blocklist (sector, 0, 0, length & (GRUB_DISK_SECTOR_SIZE - 1), ctx);
}
else
{
ctx->start_sector = sector;
ctx->num_sectors = length >> GRUB_DISK_SECTOR_BITS;
}
}
static grub_err_t
grub_cmd_blocklist (grub_command_t cmd __attribute__ ((unused)),
int argc, char **args)
{
grub_file_t file;
char buf[GRUB_DISK_SECTOR_SIZE];
struct blocklist_ctx ctx = {
.start_sector = 0,
.num_sectors = 0,
.num_entries = 0,
.part_start = 0
};
if (argc < 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
file = grub_file_open (args[0], GRUB_FILE_TYPE_PRINT_BLOCKLIST
| GRUB_FILE_TYPE_NO_DECOMPRESS);
if (! file)
return grub_errno;
if (! file->device->disk)
return grub_error (GRUB_ERR_BAD_DEVICE,
"this command is available only for disk devices");
ctx.part_start = grub_partition_get_start (file->device->disk->partition);
file->read_hook = read_blocklist;
file->read_hook_data = &ctx;
while (grub_file_read (file, buf, sizeof (buf)) > 0)
;
if (ctx.num_sectors > 0)
print_blocklist (ctx.start_sector, ctx.num_sectors, 0, 0, &ctx);
grub_printf("\nentry number:%d \n", ctx.num_entries);
grub_file_close (file);
return grub_errno;
}
static grub_command_t cmd;
GRUB_MOD_INIT(blocklist)
{
cmd = grub_register_command ("blocklist", grub_cmd_blocklist,
N_("FILE"), N_("Print a block list."));
}
GRUB_MOD_FINI(blocklist)
{
grub_unregister_command (cmd);
}
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/machine/biosdisk.h>
#include <grub/machine/kernel.h>
#include <grub/machine/memory.h>
#include <grub/machine/int.h>
#include <grub/disk.h>
#include <grub/dl.h>
#include <grub/mm.h>
#include <grub/types.h>
#include <grub/misc.h>
#include <grub/err.h>
#include <grub/term.h>
#include <grub/i18n.h>
GRUB_MOD_LICENSE ("GPLv3+");
static int cd_drive = 0;
static int grub_biosdisk_rw_int13_extensions (int ah, int drive, void *dap);
static int grub_biosdisk_get_num_floppies (void)
{
struct grub_bios_int_registers regs;
int drive;
/* reset the disk system first */
regs.eax = 0;
regs.edx = 0;
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
grub_bios_interrupt (0x13, &regs);
for (drive = 0; drive < 2; drive++)
{
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT | GRUB_CPU_INT_FLAGS_CARRY;
regs.edx = drive;
/* call GET DISK TYPE */
regs.eax = 0x1500;
grub_bios_interrupt (0x13, &regs);
if (regs.flags & GRUB_CPU_INT_FLAGS_CARRY)
break;
/* check if this drive exists */
if (!(regs.eax & 0x300))
break;
}
return drive;
}
/*
* Call IBM/MS INT13 Extensions (int 13 %ah=AH) for DRIVE. DAP
* is passed for disk address packet. If an error occurs, return
* non-zero, otherwise zero.
*/
static int
grub_biosdisk_rw_int13_extensions (int ah, int drive, void *dap)
{
struct grub_bios_int_registers regs;
regs.eax = ah << 8;
/* compute the address of disk_address_packet */
regs.ds = (((grub_addr_t) dap) & 0xffff0000) >> 4;
regs.esi = (((grub_addr_t) dap) & 0xffff);
regs.edx = drive;
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
grub_bios_interrupt (0x13, &regs);
return (regs.eax >> 8) & 0xff;
}
/*
* Call standard and old INT13 (int 13 %ah=AH) for DRIVE. Read/write
* NSEC sectors from COFF/HOFF/SOFF into SEGMENT. If an error occurs,
* return non-zero, otherwise zero.
*/
static int
grub_biosdisk_rw_standard (int ah, int drive, int coff, int hoff,
int soff, int nsec, int segment)
{
int ret, i;
/* Try 3 times. */
for (i = 0; i < 3; i++)
{
struct grub_bios_int_registers regs;
/* set up CHS information */
/* set %ch to low eight bits of cylinder */
regs.ecx = (coff << 8) & 0xff00;
/* set bits 6-7 of %cl to high two bits of cylinder */
regs.ecx |= (coff >> 2) & 0xc0;
/* set bits 0-5 of %cl to sector */
regs.ecx |= soff & 0x3f;
/* set %dh to head and %dl to drive */
regs.edx = (drive & 0xff) | ((hoff << 8) & 0xff00);
/* set %ah to AH */
regs.eax = (ah << 8) & 0xff00;
/* set %al to NSEC */
regs.eax |= nsec & 0xff;
regs.ebx = 0;
regs.es = segment;
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
grub_bios_interrupt (0x13, &regs);
/* check if successful */
if (!(regs.flags & GRUB_CPU_INT_FLAGS_CARRY))
return 0;
/* save return value */
ret = regs.eax >> 8;
/* if fail, reset the disk system */
regs.eax = 0;
regs.edx = (drive & 0xff);
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
grub_bios_interrupt (0x13, &regs);
}
return ret;
}
/*
* Check if LBA is supported for DRIVE. If it is supported, then return
* the major version of extensions, otherwise zero.
*/
static int
grub_biosdisk_check_int13_extensions (int drive)
{
struct grub_bios_int_registers regs;
regs.edx = drive & 0xff;
regs.eax = 0x4100;
regs.ebx = 0x55aa;
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
grub_bios_interrupt (0x13, &regs);
if (regs.flags & GRUB_CPU_INT_FLAGS_CARRY)
return 0;
if ((regs.ebx & 0xffff) != 0xaa55)
return 0;
/* check if AH=0x42 is supported */
if (!(regs.ecx & 1))
return 0;
return (regs.eax >> 8) & 0xff;
}
/*
* Return the geometry of DRIVE in CYLINDERS, HEADS and SECTORS. If an
* error occurs, then return non-zero, otherwise zero.
*/
static int
grub_biosdisk_get_diskinfo_standard (int drive,
unsigned long *cylinders,
unsigned long *heads,
unsigned long *sectors)
{
struct grub_bios_int_registers regs;
regs.eax = 0x0800;
regs.edx = drive & 0xff;
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
grub_bios_interrupt (0x13, &regs);
/* Check if unsuccessful. Ignore return value if carry isn't set to
workaround some buggy BIOSes. */
if ((regs.flags & GRUB_CPU_INT_FLAGS_CARRY) && ((regs.eax & 0xff00) != 0))
return (regs.eax & 0xff00) >> 8;
/* bogus BIOSes may not return an error number */
/* 0 sectors means no disk */
if (!(regs.ecx & 0x3f))
/* XXX 0x60 is one of the unused error numbers */
return 0x60;
/* the number of heads is counted from zero */
*heads = ((regs.edx >> 8) & 0xff) + 1;
*cylinders = (((regs.ecx >> 8) & 0xff) | ((regs.ecx << 2) & 0x0300)) + 1;
*sectors = regs.ecx & 0x3f;
return 0;
}
static int
grub_biosdisk_get_diskinfo_real (int drive, void *drp, grub_uint16_t ax)
{
struct grub_bios_int_registers regs;
regs.eax = ax;
/* compute the address of drive parameters */
regs.esi = ((grub_addr_t) drp) & 0xf;
regs.ds = ((grub_addr_t) drp) >> 4;
regs.edx = drive & 0xff;
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
grub_bios_interrupt (0x13, &regs);
/* Check if unsuccessful. Ignore return value if carry isn't set to
workaround some buggy BIOSes. */
if ((regs.flags & GRUB_CPU_INT_FLAGS_CARRY) && ((regs.eax & 0xff00) != 0))
return (regs.eax & 0xff00) >> 8;
return 0;
}
/*
* Return the cdrom information of DRIVE in CDRP. If an error occurs,
* then return non-zero, otherwise zero.
*/
static int
grub_biosdisk_get_cdinfo_int13_extensions (int drive, void *cdrp)
{
return grub_biosdisk_get_diskinfo_real (drive, cdrp, 0x4b01);
}
/*
* Return the geometry of DRIVE in a drive parameters, DRP. If an error
* occurs, then return non-zero, otherwise zero.
*/
static int
grub_biosdisk_get_diskinfo_int13_extensions (int drive, void *drp)
{
return grub_biosdisk_get_diskinfo_real (drive, drp, 0x4800);
}
static int
grub_biosdisk_get_drive (const char *name)
{
unsigned long drive;
if (name[0] == 'c' && name[1] == 'd' && name[2] == 0 && cd_drive)
return cd_drive;
if ((name[0] != 'f' && name[0] != 'h') || name[1] != 'd')
goto fail;
drive = grub_strtoul (name + 2, 0, 10);
if (grub_errno != GRUB_ERR_NONE)
goto fail;
if (name[0] == 'h')
drive += 0x80;
return (int) drive ;
fail:
grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a biosdisk");
return -1;
}
static int
grub_biosdisk_call_hook (grub_disk_dev_iterate_hook_t hook, void *hook_data,
int drive)
{
char name[10];
if (cd_drive && drive == cd_drive)
return hook ("cd", hook_data);
grub_snprintf (name, sizeof (name),
(drive & 0x80) ? "hd%d" : "fd%d", drive & (~0x80));
return hook (name, hook_data);
}
static int
grub_biosdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
grub_disk_pull_t pull)
{
int num_floppies;
int drive;
/* For hard disks, attempt to read the MBR. */
switch (pull)
{
case GRUB_DISK_PULL_NONE:
for (drive = 0x80; drive < 0x90; drive++)
{
if (grub_biosdisk_rw_standard (0x02, drive, 0, 0, 1, 1,
GRUB_MEMORY_MACHINE_SCRATCH_SEG) != 0)
{
grub_dprintf ("disk", "Read error when probing drive 0x%2x\n", drive);
break;
}
if (grub_biosdisk_call_hook (hook, hook_data, drive))
return 1;
}
return 0;
case GRUB_DISK_PULL_REMOVABLE:
if (cd_drive)
{
if (grub_biosdisk_call_hook (hook, hook_data, cd_drive))
return 1;
}
/* For floppy disks, we can get the number safely. */
num_floppies = grub_biosdisk_get_num_floppies ();
for (drive = 0; drive < num_floppies; drive++)
if (grub_biosdisk_call_hook (hook, hook_data, drive))
return 1;
return 0;
default:
return 0;
}
return 0;
}
#pragma pack(1)
typedef struct ventoy_part_table
{
grub_uint8_t Active; // 0x00 0x80
grub_uint8_t StartHead;
grub_uint16_t StartSector : 6;
grub_uint16_t StartCylinder : 10;
grub_uint8_t FsFlag;
grub_uint8_t EndHead;
grub_uint16_t EndSector : 6;
grub_uint16_t EndCylinder : 10;
grub_uint32_t StartSectorId;
grub_uint32_t SectorCount;
}ventoy_part_table;
typedef struct ventoy_mbr_head
{
grub_uint8_t BootCode[446];
ventoy_part_table PartTbl[4];
grub_uint8_t Byte55;
grub_uint8_t ByteAA;
}ventoy_mbr_head;
#pragma pack()
static grub_err_t
grub_biosdisk_rw (int cmd, grub_disk_t disk,
grub_disk_addr_t sector, grub_size_t size,
unsigned segment);
static int ventoy_is_mbr_match(ventoy_mbr_head *head)
{
grub_uint32_t PartStartSector;
if (head->Byte55 != 0x55 || head->ByteAA != 0xAA) {
return 0;
}
if (head->PartTbl[2].SectorCount > 0 || head->PartTbl[3].SectorCount > 0) {
return 0;
}
if (head->PartTbl[0].FsFlag != 0x07 || head->PartTbl[0].StartSectorId != 2048) {
return 0;
}
if (head->PartTbl[1].Active != 0x80 || head->PartTbl[1].FsFlag != 0xEF) {
return 0;
}
PartStartSector = head->PartTbl[0].StartSectorId + head->PartTbl[0].SectorCount;
if (head->PartTbl[1].StartSectorId != PartStartSector || head->PartTbl[1].SectorCount != 65536) {
return 0;
}
return 1;
}
static grub_err_t
grub_biosdisk_open (const char *name, grub_disk_t disk)
{
grub_uint64_t total_sectors = 0;
int drive;
struct grub_biosdisk_data *data;
drive = grub_biosdisk_get_drive (name);
if (drive < 0)
return grub_errno;
disk->id = drive;
data = (struct grub_biosdisk_data *) grub_zalloc (sizeof (*data));
if (! data)
return grub_errno;
data->drive = drive;
if ((cd_drive) && (drive == cd_drive))
{
data->flags = GRUB_BIOSDISK_FLAG_LBA | GRUB_BIOSDISK_FLAG_CDROM;
data->sectors = 8;
disk->log_sector_size = 11;
/* TODO: get the correct size. */
total_sectors = GRUB_DISK_SIZE_UNKNOWN;
}
else
{
/* HDD */
int version;
disk->log_sector_size = 9;
version = grub_biosdisk_check_int13_extensions (drive);
if (version)
{
struct grub_biosdisk_drp *drp
= (struct grub_biosdisk_drp *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
/* Clear out the DRP. */
grub_memset (drp, 0, sizeof (*drp));
drp->size = sizeof (*drp);
if (! grub_biosdisk_get_diskinfo_int13_extensions (drive, drp))
{
data->flags = GRUB_BIOSDISK_FLAG_LBA;
if (drp->total_sectors)
total_sectors = drp->total_sectors;
else
/* Some buggy BIOSes doesn't return the total sectors
correctly but returns zero. So if it is zero, compute
it by C/H/S returned by the LBA BIOS call. */
total_sectors = ((grub_uint64_t) drp->cylinders)
* drp->heads * drp->sectors;
if (drp->bytes_per_sector
&& !(drp->bytes_per_sector & (drp->bytes_per_sector - 1))
&& drp->bytes_per_sector >= 512
&& drp->bytes_per_sector <= 16384)
{
for (disk->log_sector_size = 0;
(1 << disk->log_sector_size) < drp->bytes_per_sector;
disk->log_sector_size++);
}
}
}
}
if (! (data->flags & GRUB_BIOSDISK_FLAG_CDROM))
{
if (grub_biosdisk_get_diskinfo_standard (drive,
&data->cylinders,
&data->heads,
&data->sectors) != 0)
{
if (total_sectors && (data->flags & GRUB_BIOSDISK_FLAG_LBA))
{
data->sectors = 63;
data->heads = 255;
data->cylinders
= grub_divmod64 (total_sectors
+ data->heads * data->sectors - 1,
data->heads * data->sectors, 0);
}
else
{
grub_free (data);
return grub_error (GRUB_ERR_BAD_DEVICE, "%s cannot get C/H/S values", disk->name);
}
}
if (data->sectors == 0)
data->sectors = 63;
if (data->heads == 0)
data->heads = 255;
if (! total_sectors)
total_sectors = ((grub_uint64_t) data->cylinders)
* data->heads * data->sectors;
}
disk->total_sectors = total_sectors;
/* Limit the max to 0x7f because of Phoenix EDD. */
disk->max_agglomerate = 0x7f >> GRUB_DISK_CACHE_BITS;
COMPILE_TIME_ASSERT ((0x7f >> GRUB_DISK_CACHE_BITS
<< (GRUB_DISK_SECTOR_BITS + GRUB_DISK_CACHE_BITS))
+ sizeof (struct grub_biosdisk_dap)
< GRUB_MEMORY_MACHINE_SCRATCH_SIZE);
disk->data = data;
//fixup some buggy bios
if (total_sectors > (16434495 - 2097152) && total_sectors < (16434495 + 2097152) &&
(data->flags & GRUB_BIOSDISK_FLAG_LBA) > 0 && (data->flags & GRUB_BIOSDISK_FLAG_CDROM) == 0) {
if (grub_biosdisk_rw(0, disk, 0, 1, GRUB_MEMORY_MACHINE_SCRATCH_SEG) == 0) {
ventoy_mbr_head *mbr = (ventoy_mbr_head *)GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
if (ventoy_is_mbr_match(mbr)) {
total_sectors = mbr->PartTbl[1].StartSectorId + mbr->PartTbl[1].SectorCount + 1;
if (disk->total_sectors < total_sectors) {
disk->total_sectors = total_sectors;
}
}
}
}
return GRUB_ERR_NONE;
}
static void
grub_biosdisk_close (grub_disk_t disk)
{
grub_free (disk->data);
}
/* For readability. */
#define GRUB_BIOSDISK_READ 0
#define GRUB_BIOSDISK_WRITE 1
#define GRUB_BIOSDISK_CDROM_RETRY_COUNT 3
static grub_err_t
grub_biosdisk_rw (int cmd, grub_disk_t disk,
grub_disk_addr_t sector, grub_size_t size,
unsigned segment)
{
struct grub_biosdisk_data *data = disk->data;
/* VirtualBox fails with sectors above 2T on CDs.
Since even BD-ROMS are never that big anyway, return error. */
if ((data->flags & GRUB_BIOSDISK_FLAG_CDROM)
&& (sector >> 32))
return grub_error (GRUB_ERR_OUT_OF_RANGE,
N_("attempt to read or write outside of disk `%s'"),
disk->name);
if (data->flags & GRUB_BIOSDISK_FLAG_LBA)
{
struct grub_biosdisk_dap *dap;
dap = (struct grub_biosdisk_dap *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR
+ (data->sectors
<< disk->log_sector_size));
dap->length = sizeof (*dap);
dap->reserved = 0;
dap->blocks = size;
dap->buffer = segment << 16; /* The format SEGMENT:ADDRESS. */
dap->block = sector;
if (data->flags & GRUB_BIOSDISK_FLAG_CDROM)
{
int i;
if (cmd)
return grub_error (GRUB_ERR_WRITE_ERROR, N_("cannot write to CD-ROM"));
for (i = 0; i < GRUB_BIOSDISK_CDROM_RETRY_COUNT; i++)
if (! grub_biosdisk_rw_int13_extensions (0x42, data->drive, dap))
break;
if (i == GRUB_BIOSDISK_CDROM_RETRY_COUNT)
return grub_error (GRUB_ERR_READ_ERROR, N_("failure reading sector 0x%llx "
"from `%s'"),
(unsigned long long) sector,
disk->name);
}
else
if (grub_biosdisk_rw_int13_extensions (cmd + 0x42, data->drive, dap))
{
/* Fall back to the CHS mode. */
data->flags &= ~GRUB_BIOSDISK_FLAG_LBA;
disk->total_sectors = data->cylinders * data->heads * data->sectors;
return grub_biosdisk_rw (cmd, disk, sector, size, segment);
}
}
else
{
unsigned coff, hoff, soff;
unsigned head;
/* It is impossible to reach over 8064 MiB (a bit less than LBA24) with
the traditional CHS access. */
if (sector >
1024 /* cylinders */ *
256 /* heads */ *
63 /* spt */)
return grub_error (GRUB_ERR_OUT_OF_RANGE,
N_("attempt to read or write outside of disk `%s'"),
disk->name);
soff = ((grub_uint32_t) sector) % data->sectors + 1;
head = ((grub_uint32_t) sector) / data->sectors;
hoff = head % data->heads;
coff = head / data->heads;
if (coff >= data->cylinders)
return grub_error (GRUB_ERR_OUT_OF_RANGE,
N_("attempt to read or write outside of disk `%s'"),
disk->name);
if (grub_biosdisk_rw_standard (cmd + 0x02, data->drive,
coff, hoff, soff, size, segment))
{
switch (cmd)
{
case GRUB_BIOSDISK_READ:
return grub_error (GRUB_ERR_READ_ERROR, N_("failure reading sector 0x%llx "
"from `%s'"),
(unsigned long long) sector,
disk->name);
case GRUB_BIOSDISK_WRITE:
return grub_error (GRUB_ERR_WRITE_ERROR, N_("failure writing sector 0x%llx "
"to `%s'"),
(unsigned long long) sector,
disk->name);
}
}
}
return GRUB_ERR_NONE;
}
/* Return the number of sectors which can be read safely at a time. */
static grub_size_t
get_safe_sectors (grub_disk_t disk, grub_disk_addr_t sector)
{
grub_size_t size;
grub_uint64_t offset;
struct grub_biosdisk_data *data = disk->data;
grub_uint32_t sectors = data->sectors;
/* OFFSET = SECTOR % SECTORS */
grub_divmod64 (sector, sectors, &offset);
size = sectors - offset;
return size;
}
static grub_err_t
grub_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, char *buf)
{
while (size)
{
grub_size_t len;
len = get_safe_sectors (disk, sector);
if (len > size)
len = size;
if (grub_biosdisk_rw (GRUB_BIOSDISK_READ, disk, sector, len,
GRUB_MEMORY_MACHINE_SCRATCH_SEG))
return grub_errno;
grub_memcpy (buf, (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR,
len << disk->log_sector_size);
buf += len << disk->log_sector_size;
sector += len;
size -= len;
}
return grub_errno;
}
static grub_err_t
grub_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, const char *buf)
{
struct grub_biosdisk_data *data = disk->data;
if (data->flags & GRUB_BIOSDISK_FLAG_CDROM)
return grub_error (GRUB_ERR_IO, N_("cannot write to CD-ROM"));
while (size)
{
grub_size_t len;
len = get_safe_sectors (disk, sector);
if (len > size)
len = size;
grub_memcpy ((void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR, buf,
len << disk->log_sector_size);
if (grub_biosdisk_rw (GRUB_BIOSDISK_WRITE, disk, sector, len,
GRUB_MEMORY_MACHINE_SCRATCH_SEG))
return grub_errno;
buf += len << disk->log_sector_size;
sector += len;
size -= len;
}
return grub_errno;
}
static struct grub_disk_dev grub_biosdisk_dev =
{
.name = "biosdisk",
.id = GRUB_DISK_DEVICE_BIOSDISK_ID,
.disk_iterate = grub_biosdisk_iterate,
.disk_open = grub_biosdisk_open,
.disk_close = grub_biosdisk_close,
.disk_read = grub_biosdisk_read,
.disk_write = grub_biosdisk_write,
.next = 0
};
static void
grub_disk_biosdisk_fini (void)
{
grub_disk_dev_unregister (&grub_biosdisk_dev);
}
GRUB_MOD_INIT(biosdisk)
{
struct grub_biosdisk_cdrp *cdrp
= (struct grub_biosdisk_cdrp *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
grub_uint8_t boot_drive;
if (grub_disk_firmware_is_tainted)
{
grub_puts_ (N_("Native disk drivers are in use. "
"Refusing to use firmware disk interface."));
return;
}
grub_disk_firmware_fini = grub_disk_biosdisk_fini;
grub_memset (cdrp, 0, sizeof (*cdrp));
cdrp->size = sizeof (*cdrp);
cdrp->media_type = 0xFF;
boot_drive = (grub_boot_device >> 24);
if ((! grub_biosdisk_get_cdinfo_int13_extensions (boot_drive, cdrp))
&& ((cdrp->media_type & GRUB_BIOSDISK_CDTYPE_MASK)
== GRUB_BIOSDISK_CDTYPE_NO_EMUL))
cd_drive = cdrp->drive_no;
/* Since diskboot.S rejects devices over 0x90 it must be a CD booted with
cdboot.S
*/
if (boot_drive >= 0x90)
cd_drive = boot_drive;
grub_disk_dev_register (&grub_biosdisk_dev);
}
GRUB_MOD_FINI(biosdisk)
{
grub_disk_biosdisk_fini ();
}
/* fat.c - FAT filesystem */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/fs.h>
#include <grub/disk.h>
#include <grub/file.h>
#include <grub/types.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/err.h>
#include <grub/dl.h>
#include <grub/charset.h>
#ifndef MODE_EXFAT
#include <grub/fat.h>
#else
#include <grub/exfat.h>
#endif
#include <grub/fshelp.h>
#include <grub/i18n.h>
#include <grub/time.h>
#include <grub/ventoy.h>
GRUB_MOD_LICENSE ("GPLv3+");
enum
{
GRUB_FAT_ATTR_READ_ONLY = 0x01,
GRUB_FAT_ATTR_HIDDEN = 0x02,
GRUB_FAT_ATTR_SYSTEM = 0x04,
#ifndef MODE_EXFAT
GRUB_FAT_ATTR_VOLUME_ID = 0x08,
#endif
GRUB_FAT_ATTR_DIRECTORY = 0x10,
GRUB_FAT_ATTR_ARCHIVE = 0x20,
#ifndef MODE_EXFAT
GRUB_FAT_ATTR_LONG_NAME = (GRUB_FAT_ATTR_READ_ONLY
| GRUB_FAT_ATTR_HIDDEN
| GRUB_FAT_ATTR_SYSTEM
| GRUB_FAT_ATTR_VOLUME_ID),
#endif
GRUB_FAT_ATTR_VALID = (GRUB_FAT_ATTR_READ_ONLY
| GRUB_FAT_ATTR_HIDDEN
| GRUB_FAT_ATTR_SYSTEM
| GRUB_FAT_ATTR_DIRECTORY
| GRUB_FAT_ATTR_ARCHIVE
#ifndef MODE_EXFAT
| GRUB_FAT_ATTR_VOLUME_ID
#endif
)
};
#ifdef MODE_EXFAT
typedef struct grub_exfat_bpb grub_current_fat_bpb_t;
#else
typedef struct grub_fat_bpb grub_current_fat_bpb_t;
#endif
#ifdef MODE_EXFAT
enum
{
FLAG_CONTIGUOUS = 2
};
struct grub_fat_dir_entry
{
grub_uint8_t entry_type;
union
{
grub_uint8_t placeholder[31];
struct {
grub_uint8_t secondary_count;
grub_uint16_t checksum;
grub_uint16_t attr;
grub_uint16_t reserved1;
grub_uint32_t c_time;
grub_uint32_t m_time;
grub_uint32_t a_time;
grub_uint8_t c_time_tenth;
grub_uint8_t m_time_tenth;
grub_uint8_t a_time_tenth;
grub_uint8_t reserved2[9];
} GRUB_PACKED file;
struct {
grub_uint8_t flags;
grub_uint8_t reserved1;
grub_uint8_t name_length;
grub_uint16_t name_hash;
grub_uint16_t reserved2;
grub_uint64_t valid_size;
grub_uint32_t reserved3;
grub_uint32_t first_cluster;
grub_uint64_t file_size;
} GRUB_PACKED stream_extension;
struct {
grub_uint8_t flags;
grub_uint16_t str[15];
} GRUB_PACKED file_name;
struct {
grub_uint8_t character_count;
grub_uint16_t str[15];
} GRUB_PACKED volume_label;
} GRUB_PACKED type_specific;
} GRUB_PACKED;
struct grub_fat_dir_node
{
grub_uint32_t attr;
grub_uint32_t first_cluster;
grub_uint64_t file_size;
grub_uint64_t valid_size;
int have_stream;
int is_contiguous;
};
typedef struct grub_fat_dir_node grub_fat_dir_node_t;
#else
struct grub_fat_dir_entry
{
grub_uint8_t name[11];
grub_uint8_t attr;
grub_uint8_t nt_reserved;
grub_uint8_t c_time_tenth;
grub_uint16_t c_time;
grub_uint16_t c_date;
grub_uint16_t a_date;
grub_uint16_t first_cluster_high;
grub_uint16_t w_time;
grub_uint16_t w_date;
grub_uint16_t first_cluster_low;
grub_uint32_t file_size;
} GRUB_PACKED;
struct grub_fat_long_name_entry
{
grub_uint8_t id;
grub_uint16_t name1[5];
grub_uint8_t attr;
grub_uint8_t reserved;
grub_uint8_t checksum;
grub_uint16_t name2[6];
grub_uint16_t first_cluster;
grub_uint16_t name3[2];
} GRUB_PACKED;
typedef struct grub_fat_dir_entry grub_fat_dir_node_t;
#endif
struct grub_fat_data
{
int logical_sector_bits;
grub_uint32_t num_sectors;
grub_uint32_t fat_sector;
grub_uint32_t sectors_per_fat;
int fat_size;
grub_uint32_t root_cluster;
#ifndef MODE_EXFAT
grub_uint32_t root_sector;
grub_uint32_t num_root_sectors;
#endif
int cluster_bits;
grub_uint32_t cluster_eof_mark;
grub_uint32_t cluster_sector;
grub_uint32_t num_clusters;
grub_uint32_t uuid;
};
struct grub_fshelp_node {
grub_disk_t disk;
struct grub_fat_data *data;
grub_uint8_t attr;
#ifndef MODE_EXFAT
grub_uint32_t file_size;
#else
grub_uint64_t file_size;
#endif
grub_uint32_t file_cluster;
grub_uint32_t cur_cluster_num;
grub_uint32_t cur_cluster;
#ifdef MODE_EXFAT
int is_contiguous;
#endif
};
static grub_dl_t my_mod;
#ifndef MODE_EXFAT
static int
fat_log2 (unsigned x)
{
int i;
if (x == 0)
return -1;
for (i = 0; (x & 1) == 0; i++)
x >>= 1;
if (x != 1)
return -1;
return i;
}
#endif
static struct grub_fat_data *
grub_fat_mount (grub_disk_t disk)
{
grub_current_fat_bpb_t bpb;
struct grub_fat_data *data = 0;
grub_uint32_t first_fat, magic;
if (! disk)
goto fail;
data = (struct grub_fat_data *) grub_malloc (sizeof (*data));
if (! data)
goto fail;
/* Read the BPB. */
if (grub_disk_read (disk, 0, 0, sizeof (bpb), &bpb))
goto fail;
#ifdef MODE_EXFAT
if (grub_memcmp ((const char *) bpb.oem_name, "EXFAT ",
sizeof (bpb.oem_name)) != 0)
goto fail;
#endif
/* Get the sizes of logical sectors and clusters. */
#ifdef MODE_EXFAT
data->logical_sector_bits = bpb.bytes_per_sector_shift;
#else
data->logical_sector_bits =
fat_log2 (grub_le_to_cpu16 (bpb.bytes_per_sector));
#endif
if (data->logical_sector_bits < GRUB_DISK_SECTOR_BITS
|| data->logical_sector_bits >= 16)
goto fail;
data->logical_sector_bits -= GRUB_DISK_SECTOR_BITS;
#ifdef MODE_EXFAT
data->cluster_bits = bpb.sectors_per_cluster_shift;
#else
data->cluster_bits = fat_log2 (bpb.sectors_per_cluster);
#endif
if (data->cluster_bits < 0 || data->cluster_bits > 25)
goto fail;
data->cluster_bits += data->logical_sector_bits;
/* Get information about FATs. */
#ifdef MODE_EXFAT
data->fat_sector = (grub_le_to_cpu32 (bpb.num_reserved_sectors)
<< data->logical_sector_bits);
#else
data->fat_sector = (grub_le_to_cpu16 (bpb.num_reserved_sectors)
<< data->logical_sector_bits);
#endif
if (data->fat_sector == 0)
goto fail;
#ifdef MODE_EXFAT
data->sectors_per_fat = (grub_le_to_cpu32 (bpb.sectors_per_fat)
<< data->logical_sector_bits);
#else
data->sectors_per_fat = ((bpb.sectors_per_fat_16
? grub_le_to_cpu16 (bpb.sectors_per_fat_16)
: grub_le_to_cpu32 (bpb.version_specific.fat32.sectors_per_fat_32))
<< data->logical_sector_bits);
#endif
if (data->sectors_per_fat == 0)
goto fail;
/* Get the number of sectors in this volume. */
#ifdef MODE_EXFAT
data->num_sectors = ((grub_le_to_cpu64 (bpb.num_total_sectors))
<< data->logical_sector_bits);
#else
data->num_sectors = ((bpb.num_total_sectors_16
? grub_le_to_cpu16 (bpb.num_total_sectors_16)
: grub_le_to_cpu32 (bpb.num_total_sectors_32))
<< data->logical_sector_bits);
#endif
if (data->num_sectors == 0)
goto fail;
/* Get information about the root directory. */
if (bpb.num_fats == 0)
goto fail;
#ifndef MODE_EXFAT
data->root_sector = data->fat_sector + bpb.num_fats * data->sectors_per_fat;
data->num_root_sectors
= ((((grub_uint32_t) grub_le_to_cpu16 (bpb.num_root_entries)
* sizeof (struct grub_fat_dir_entry)
+ grub_le_to_cpu16 (bpb.bytes_per_sector) - 1)
>> (data->logical_sector_bits + GRUB_DISK_SECTOR_BITS))
<< (data->logical_sector_bits));
#endif
#ifdef MODE_EXFAT
data->cluster_sector = (grub_le_to_cpu32 (bpb.cluster_offset)
<< data->logical_sector_bits);
data->num_clusters = (grub_le_to_cpu32 (bpb.cluster_count)
<< data->logical_sector_bits);
#else
data->cluster_sector = data->root_sector + data->num_root_sectors;
data->num_clusters = (((data->num_sectors - data->cluster_sector)
>> data->cluster_bits)
+ 2);
#endif
if (data->num_clusters <= 2)
goto fail;
#ifdef MODE_EXFAT
{
/* exFAT. */
data->root_cluster = grub_le_to_cpu32 (bpb.root_cluster);
data->fat_size = 32;
data->cluster_eof_mark = 0xffffffff;
if ((bpb.volume_flags & grub_cpu_to_le16_compile_time (0x1))
&& bpb.num_fats > 1)
data->fat_sector += data->sectors_per_fat;
}
#else
if (! bpb.sectors_per_fat_16)
{
/* FAT32. */
grub_uint16_t flags = grub_le_to_cpu16 (bpb.version_specific.fat32.extended_flags);
data->root_cluster = grub_le_to_cpu32 (bpb.version_specific.fat32.root_cluster);
data->fat_size = 32;
data->cluster_eof_mark = 0x0ffffff8;
if (flags & 0x80)
{
/* Get an active FAT. */
unsigned active_fat = flags & 0xf;
if (active_fat > bpb.num_fats)
goto fail;
data->fat_sector += active_fat * data->sectors_per_fat;
}
if (bpb.num_root_entries != 0 || bpb.version_specific.fat32.fs_version != 0)
goto fail;
}
else
{
/* FAT12 or FAT16. */
data->root_cluster = ~0U;
if (data->num_clusters <= 4085 + 2)
{
/* FAT12. */
data->fat_size = 12;
data->cluster_eof_mark = 0x0ff8;
}
else
{
/* FAT16. */
data->fat_size = 16;
data->cluster_eof_mark = 0xfff8;
}
}
#endif
/* More sanity checks. */
if (data->num_sectors <= data->fat_sector)
goto fail;
if (grub_disk_read (disk,
data->fat_sector,
0,
sizeof (first_fat),
&first_fat))
goto fail;
first_fat = grub_le_to_cpu32 (first_fat);
if (data->fat_size == 32)
{
first_fat &= 0x0fffffff;
magic = 0x0fffff00;
}
else if (data->fat_size == 16)
{
first_fat &= 0x0000ffff;
magic = 0xff00;
}
else
{
first_fat &= 0x00000fff;
magic = 0x0f00;
}
/* Serial number. */
#ifdef MODE_EXFAT
data->uuid = grub_le_to_cpu32 (bpb.num_serial);
#else
if (bpb.sectors_per_fat_16)
data->uuid = grub_le_to_cpu32 (bpb.version_specific.fat12_or_fat16.num_serial);
else
data->uuid = grub_le_to_cpu32 (bpb.version_specific.fat32.num_serial);
#endif
#ifndef MODE_EXFAT
/* Ignore the 3rd bit, because some BIOSes assigns 0xF0 to the media
descriptor, even if it is a so-called superfloppy (e.g. an USB key).
The check may be too strict for this kind of stupid BIOSes, as
they overwrite the media descriptor. */
if ((first_fat | 0x8) != (magic | bpb.media | 0x8))
goto fail;
#else
(void) magic;
#endif
return data;
fail:
grub_free (data);
grub_error (GRUB_ERR_BAD_FS, "not a FAT filesystem");
return 0;
}
static grub_ssize_t
grub_fat_read_data (grub_disk_t disk, grub_fshelp_node_t node,
grub_disk_read_hook_t read_hook, void *read_hook_data,
grub_off_t offset, grub_size_t len, char *buf)
{
grub_size_t size;
grub_uint32_t logical_cluster;
unsigned logical_cluster_bits;
grub_ssize_t ret = 0;
unsigned long sector;
#ifndef MODE_EXFAT
/* This is a special case. FAT12 and FAT16 doesn't have the root directory
in clusters. */
if (node->file_cluster == ~0U)
{
size = (node->data->num_root_sectors << GRUB_DISK_SECTOR_BITS) - offset;
if (size > len)
size = len;
if (grub_disk_read (disk, node->data->root_sector, offset, size, buf))
return -1;
return size;
}
#endif
#ifdef MODE_EXFAT
if (node->is_contiguous)
{
/* Read the data here. */
sector = (node->data->cluster_sector
+ ((node->file_cluster - 2)
<< node->data->cluster_bits));
disk->read_hook = read_hook;
disk->read_hook_data = read_hook_data;
grub_disk_read (disk, sector + (offset >> GRUB_DISK_SECTOR_BITS),
offset & (GRUB_DISK_SECTOR_SIZE - 1), len, buf);
disk->read_hook = 0;
if (grub_errno)
return -1;
return len;
}
#endif
/* Calculate the logical cluster number and offset. */
logical_cluster_bits = (node->data->cluster_bits
+ GRUB_DISK_SECTOR_BITS);
logical_cluster = offset >> logical_cluster_bits;
offset &= (1ULL << logical_cluster_bits) - 1;
if (logical_cluster < node->cur_cluster_num)
{
node->cur_cluster_num = 0;
node->cur_cluster = node->file_cluster;
}
while (len)
{
while (logical_cluster > node->cur_cluster_num)
{
/* Find next cluster. */
grub_uint32_t next_cluster;
grub_uint32_t fat_offset;
switch (node->data->fat_size)
{
case 32:
fat_offset = node->cur_cluster << 2;
break;
case 16:
fat_offset = node->cur_cluster << 1;
break;
default:
/* case 12: */
fat_offset = node->cur_cluster + (node->cur_cluster >> 1);
break;
}
/* Read the FAT. */
if (grub_disk_read (disk, node->data->fat_sector, fat_offset,
(node->data->fat_size + 7) >> 3,
(char *) &next_cluster))
return -1;
next_cluster = grub_le_to_cpu32 (next_cluster);
switch (node->data->fat_size)
{
case 16:
next_cluster &= 0xFFFF;
break;
case 12:
if (node->cur_cluster & 1)
next_cluster >>= 4;
next_cluster &= 0x0FFF;
break;
}
grub_dprintf ("fat", "fat_size=%d, next_cluster=%u\n",
node->data->fat_size, next_cluster);
/* Check the end. */
if (next_cluster >= node->data->cluster_eof_mark)
return ret;
if (next_cluster < 2 || next_cluster >= node->data->num_clusters)
{
grub_error (GRUB_ERR_BAD_FS, "invalid cluster %u",
next_cluster);
return -1;
}
node->cur_cluster = next_cluster;
node->cur_cluster_num++;
}
/* Read the data here. */
sector = (node->data->cluster_sector
+ ((node->cur_cluster - 2)
<< node->data->cluster_bits));
size = (1 << logical_cluster_bits) - offset;
if (size > len)
size = len;
disk->read_hook = read_hook;
disk->read_hook_data = read_hook_data;
grub_disk_read (disk, sector, offset, size, buf);
disk->read_hook = 0;
if (grub_errno)
return -1;
len -= size;
buf += size;
ret += size;
logical_cluster++;
offset = 0;
}
return ret;
}
struct grub_fat_iterate_context
{
#ifdef MODE_EXFAT
struct grub_fat_dir_node dir;
#else
struct grub_fat_dir_entry dir;
#endif
char *filename;
grub_uint16_t *unibuf;
grub_ssize_t offset;
};
static grub_err_t
grub_fat_iterate_init (struct grub_fat_iterate_context *ctxt)
{
ctxt->offset = -sizeof (struct grub_fat_dir_entry);
#ifndef MODE_EXFAT
/* Allocate space enough to hold a long name. */
ctxt->filename = grub_malloc (0x40 * 13 * GRUB_MAX_UTF8_PER_UTF16 + 1);
ctxt->unibuf = (grub_uint16_t *) grub_malloc (0x40 * 13 * 2);
#else
ctxt->unibuf = grub_malloc (15 * 256 * 2);
ctxt->filename = grub_malloc (15 * 256 * GRUB_MAX_UTF8_PER_UTF16 + 1);
#endif
if (! ctxt->filename || ! ctxt->unibuf)
{
grub_free (ctxt->filename);
grub_free (ctxt->unibuf);
return grub_errno;
}
return GRUB_ERR_NONE;
}
static void
grub_fat_iterate_fini (struct grub_fat_iterate_context *ctxt)
{
grub_free (ctxt->filename);
grub_free (ctxt->unibuf);
}
#ifdef MODE_EXFAT
static grub_err_t
grub_fat_iterate_dir_next (grub_fshelp_node_t node,
struct grub_fat_iterate_context *ctxt)
{
grub_memset (&ctxt->dir, 0, sizeof (ctxt->dir));
while (1)
{
struct grub_fat_dir_entry dir;
ctxt->offset += sizeof (dir);
if (grub_fat_read_data (node->disk, node, 0, 0, ctxt->offset, sizeof (dir),
(char *) &dir)
!= sizeof (dir))
break;
if (dir.entry_type == 0)
break;
if (!(dir.entry_type & 0x80))
continue;
if (dir.entry_type == 0x85)
{
unsigned i, nsec, slots = 0;
nsec = dir.type_specific.file.secondary_count;
ctxt->dir.attr = grub_cpu_to_le16 (dir.type_specific.file.attr);
ctxt->dir.have_stream = 0;
for (i = 0; i < nsec; i++)
{
struct grub_fat_dir_entry sec;
ctxt->offset += sizeof (sec);
if (grub_fat_read_data (node->disk, node, 0, 0,
ctxt->offset, sizeof (sec), (char *) &sec)
!= sizeof (sec))
break;
if (!(sec.entry_type & 0x80))
continue;
if (!(sec.entry_type & 0x40))
break;
switch (sec.entry_type)
{
case 0xc0:
ctxt->dir.first_cluster = grub_cpu_to_le32 (sec.type_specific.stream_extension.first_cluster);
ctxt->dir.valid_size
= grub_cpu_to_le64 (sec.type_specific.stream_extension.valid_size);
ctxt->dir.file_size
= grub_cpu_to_le64 (sec.type_specific.stream_extension.file_size);
ctxt->dir.have_stream = 1;
ctxt->dir.is_contiguous = !!(sec.type_specific.stream_extension.flags
& grub_cpu_to_le16_compile_time (FLAG_CONTIGUOUS));
break;
case 0xc1:
{
int j;
for (j = 0; j < 15; j++)
ctxt->unibuf[slots * 15 + j]
= grub_le_to_cpu16 (sec.type_specific.file_name.str[j]);
slots++;
}
break;
default:
grub_dprintf ("exfat", "unknown secondary type 0x%02x\n",
sec.entry_type);
}
}
if (i != nsec)
{
ctxt->offset -= sizeof (dir);
continue;
}
*grub_utf16_to_utf8 ((grub_uint8_t *) ctxt->filename, ctxt->unibuf,
slots * 15) = '\0';
return 0;
}
/* Allocation bitmap. */
if (dir.entry_type == 0x81)
continue;
/* Upcase table. */
if (dir.entry_type == 0x82)
continue;
/* Volume label. */
if (dir.entry_type == 0x83)
continue;
grub_dprintf ("exfat", "unknown primary type 0x%02x\n",
dir.entry_type);
}
return grub_errno ? : GRUB_ERR_EOF;
}
#else
static grub_err_t
grub_fat_iterate_dir_next (grub_fshelp_node_t node,
struct grub_fat_iterate_context *ctxt)
{
char *filep = 0;
int checksum = -1;
int slot = -1, slots = -1;
while (1)
{
unsigned i;
/* Adjust the offset. */
ctxt->offset += sizeof (ctxt->dir);
/* Read a directory entry. */
if (grub_fat_read_data (node->disk, node, 0, 0,
ctxt->offset, sizeof (ctxt->dir),
(char *) &ctxt->dir)
!= sizeof (ctxt->dir) || ctxt->dir.name[0] == 0)
break;
/* Handle long name entries. */
if (ctxt->dir.attr == GRUB_FAT_ATTR_LONG_NAME)
{
struct grub_fat_long_name_entry *long_name
= (struct grub_fat_long_name_entry *) &ctxt->dir;
grub_uint8_t id = long_name->id;
if (id & 0x40)
{
id &= 0x3f;
slots = slot = id;
checksum = long_name->checksum;
}
if (id != slot || slot == 0 || checksum != long_name->checksum)
{
checksum = -1;
continue;
}
slot--;
grub_memcpy (ctxt->unibuf + slot * 13, long_name->name1, 5 * 2);
grub_memcpy (ctxt->unibuf + slot * 13 + 5, long_name->name2, 6 * 2);
grub_memcpy (ctxt->unibuf + slot * 13 + 11, long_name->name3, 2 * 2);
continue;
}
/* Check if this entry is valid. */
if (ctxt->dir.name[0] == 0xe5 || (ctxt->dir.attr & ~GRUB_FAT_ATTR_VALID))
continue;
/* This is a workaround for Japanese. */
if (ctxt->dir.name[0] == 0x05)
ctxt->dir.name[0] = 0xe5;
if (checksum != -1 && slot == 0)
{
grub_uint8_t sum;
for (sum = 0, i = 0; i < sizeof (ctxt->dir.name); i++)
sum = ((sum >> 1) | (sum << 7)) + ctxt->dir.name[i];
if (sum == checksum)
{
int u;
for (u = 0; u < slots * 13; u++)
ctxt->unibuf[u] = grub_le_to_cpu16 (ctxt->unibuf[u]);
*grub_utf16_to_utf8 ((grub_uint8_t *) ctxt->filename,
ctxt->unibuf,
slots * 13) = '\0';
return GRUB_ERR_NONE;
}
checksum = -1;
}
/* Convert the 8.3 file name. */
filep = ctxt->filename;
if (ctxt->dir.attr & GRUB_FAT_ATTR_VOLUME_ID)
{
for (i = 0; i < sizeof (ctxt->dir.name) && ctxt->dir.name[i]; i++)
*filep++ = ctxt->dir.name[i];
while (i > 0 && ctxt->dir.name[i - 1] == ' ')
{
filep--;
i--;
}
}
else
{
for (i = 0; i < 8 && ctxt->dir.name[i]; i++)
*filep++ = grub_tolower (ctxt->dir.name[i]);
while (i > 0 && ctxt->dir.name[i - 1] == ' ')
{
filep--;
i--;
}
/* XXX should we check that dir position is 0 or 1? */
if (i > 2 || filep[0] != '.' || (i == 2 && filep[1] != '.'))
*filep++ = '.';
for (i = 8; i < 11 && ctxt->dir.name[i]; i++)
*filep++ = grub_tolower (ctxt->dir.name[i]);
while (i > 8 && ctxt->dir.name[i - 1] == ' ')
{
filep--;
i--;
}
if (i == 8)
filep--;
}
*filep = '\0';
return GRUB_ERR_NONE;
}
return grub_errno ? : GRUB_ERR_EOF;
}
#endif
static grub_err_t lookup_file (grub_fshelp_node_t node,
const char *name,
grub_fshelp_node_t *foundnode,
enum grub_fshelp_filetype *foundtype)
{
grub_err_t err;
struct grub_fat_iterate_context ctxt;
err = grub_fat_iterate_init (&ctxt);
if (err)
return err;
while (!(err = grub_fat_iterate_dir_next (node, &ctxt)))
{
#ifdef MODE_EXFAT
if (!ctxt.dir.have_stream)
continue;
#else
if (ctxt.dir.attr & GRUB_FAT_ATTR_VOLUME_ID)
continue;
#endif
if (grub_strcasecmp (name, ctxt.filename) == 0)
{
*foundnode = grub_malloc (sizeof (struct grub_fshelp_node));
if (!*foundnode)
return grub_errno;
(*foundnode)->attr = ctxt.dir.attr;
#ifdef MODE_EXFAT
(*foundnode)->file_size = ctxt.dir.file_size;
(*foundnode)->file_cluster = ctxt.dir.first_cluster;
(*foundnode)->is_contiguous = ctxt.dir.is_contiguous;
#else
(*foundnode)->file_size = grub_le_to_cpu32 (ctxt.dir.file_size);
(*foundnode)->file_cluster = ((grub_le_to_cpu16 (ctxt.dir.first_cluster_high) << 16)
| grub_le_to_cpu16 (ctxt.dir.first_cluster_low));
/* If directory points to root, starting cluster is 0 */
if (!(*foundnode)->file_cluster)
(*foundnode)->file_cluster = node->data->root_cluster;
#endif
(*foundnode)->cur_cluster_num = ~0U;
(*foundnode)->data = node->data;
(*foundnode)->disk = node->disk;
*foundtype = ((*foundnode)->attr & GRUB_FAT_ATTR_DIRECTORY) ? GRUB_FSHELP_DIR : GRUB_FSHELP_REG;
grub_fat_iterate_fini (&ctxt);
return GRUB_ERR_NONE;
}
}
grub_fat_iterate_fini (&ctxt);
if (err == GRUB_ERR_EOF)
err = 0;
return err;
}
static grub_err_t
grub_fat_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook,
void *hook_data)
{
struct grub_fat_data *data = 0;
grub_disk_t disk = device->disk;
grub_fshelp_node_t found = NULL;
grub_err_t err;
struct grub_fat_iterate_context ctxt;
grub_dl_ref (my_mod);
data = grub_fat_mount (disk);
if (! data)
goto fail;
struct grub_fshelp_node root = {
.data = data,
.disk = disk,
.attr = GRUB_FAT_ATTR_DIRECTORY,
.file_size = 0,
.file_cluster = data->root_cluster,
.cur_cluster_num = ~0U,
.cur_cluster = 0,
#ifdef MODE_EXFAT
.is_contiguous = 0,
#endif
};
err = grub_fshelp_find_file_lookup (path, &root, &found, lookup_file, NULL, GRUB_FSHELP_DIR);
if (err)
goto fail;
err = grub_fat_iterate_init (&ctxt);
if (err)
goto fail;
while (!(err = grub_fat_iterate_dir_next (found, &ctxt)))
{
struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info));
info.dir = !! (ctxt.dir.attr & GRUB_FAT_ATTR_DIRECTORY);
info.case_insensitive = 1;
#ifdef MODE_EXFAT
if (!ctxt.dir.have_stream)
continue;
#else
if (ctxt.dir.attr & GRUB_FAT_ATTR_VOLUME_ID)
continue;
#endif
if (hook (ctxt.filename, &info, hook_data))
break;
}
grub_fat_iterate_fini (&ctxt);
if (err == GRUB_ERR_EOF)
err = 0;
fail:
if (found != &root)
grub_free (found);
grub_free (data);
grub_dl_unref (my_mod);
return grub_errno;
}
static grub_err_t
grub_fat_open (grub_file_t file, const char *name)
{
struct grub_fat_data *data = 0;
grub_fshelp_node_t found = NULL;
grub_err_t err;
grub_disk_t disk = file->device->disk;
grub_dl_ref (my_mod);
data = grub_fat_mount (disk);
if (! data)
goto fail;
struct grub_fshelp_node root = {
.data = data,
.disk = disk,
.attr = GRUB_FAT_ATTR_DIRECTORY,
.file_size = 0,
.file_cluster = data->root_cluster,
.cur_cluster_num = ~0U,
.cur_cluster = 0,
#ifdef MODE_EXFAT
.is_contiguous = 0,
#endif
};
err = grub_fshelp_find_file_lookup (name, &root, &found, lookup_file, NULL, GRUB_FSHELP_REG);
if (err)
goto fail;
file->data = found;
file->size = found->file_size;
return GRUB_ERR_NONE;
fail:
if (found != &root)
grub_free (found);
grub_free (data);
grub_dl_unref (my_mod);
return grub_errno;
}
static grub_ssize_t
grub_fat_read (grub_file_t file, char *buf, grub_size_t len)
{
return grub_fat_read_data (file->device->disk, file->data,
file->read_hook, file->read_hook_data,
file->offset, len, buf);
}
static grub_err_t
grub_fat_close (grub_file_t file)
{
grub_fshelp_node_t node = file->data;
grub_free (node->data);
grub_free (node);
grub_dl_unref (my_mod);
return grub_errno;
}
#ifdef MODE_EXFAT
static grub_err_t
grub_fat_label (grub_device_t device, char **label)
{
struct grub_fat_dir_entry dir;
grub_ssize_t offset = -sizeof(dir);
grub_disk_t disk = device->disk;
struct grub_fshelp_node root = {
.disk = disk,
.attr = GRUB_FAT_ATTR_DIRECTORY,
.file_size = 0,
.cur_cluster_num = ~0U,
.cur_cluster = 0,
.is_contiguous = 0,
};
root.data = grub_fat_mount (disk);
if (! root.data)
return grub_errno;
root.file_cluster = root.data->root_cluster;
*label = NULL;
while (1)
{
offset += sizeof (dir);
if (grub_fat_read_data (disk, &root, 0, 0,
offset, sizeof (dir), (char *) &dir)
!= sizeof (dir))
break;
if (dir.entry_type == 0)
break;
if (!(dir.entry_type & 0x80))
continue;
/* Volume label. */
if (dir.entry_type == 0x83)
{
grub_size_t chc;
grub_uint16_t t[ARRAY_SIZE (dir.type_specific.volume_label.str)];
grub_size_t i;
*label = grub_malloc (ARRAY_SIZE (dir.type_specific.volume_label.str)
* GRUB_MAX_UTF8_PER_UTF16 + 1);
if (!*label)
{
grub_free (root.data);
return grub_errno;
}
chc = dir.type_specific.volume_label.character_count;
if (chc > ARRAY_SIZE (dir.type_specific.volume_label.str))
chc = ARRAY_SIZE (dir.type_specific.volume_label.str);
for (i = 0; i < chc; i++)
t[i] = grub_le_to_cpu16 (dir.type_specific.volume_label.str[i]);
*grub_utf16_to_utf8 ((grub_uint8_t *) *label, t, chc) = '\0';
}
}
grub_free (root.data);
return grub_errno;
}
#else
static grub_err_t
grub_fat_label (grub_device_t device, char **label)
{
grub_disk_t disk = device->disk;
grub_err_t err;
struct grub_fat_iterate_context ctxt;
struct grub_fshelp_node root = {
.disk = disk,
.attr = GRUB_FAT_ATTR_DIRECTORY,
.file_size = 0,
.cur_cluster_num = ~0U,
.cur_cluster = 0,
};
*label = 0;
grub_dl_ref (my_mod);
root.data = grub_fat_mount (disk);
if (! root.data)
goto fail;
root.file_cluster = root.data->root_cluster;
err = grub_fat_iterate_init (&ctxt);
if (err)
goto fail;
while (!(err = grub_fat_iterate_dir_next (&root, &ctxt)))
if ((ctxt.dir.attr & ~GRUB_FAT_ATTR_ARCHIVE) == GRUB_FAT_ATTR_VOLUME_ID)
{
*label = grub_strdup (ctxt.filename);
break;
}
grub_fat_iterate_fini (&ctxt);
fail:
grub_dl_unref (my_mod);
grub_free (root.data);
return grub_errno;
}
#endif
static grub_err_t
grub_fat_uuid (grub_device_t device, char **uuid)
{
struct grub_fat_data *data;
grub_disk_t disk = device->disk;
grub_dl_ref (my_mod);
data = grub_fat_mount (disk);
if (data)
{
char *ptr;
*uuid = grub_xasprintf ("%04x-%04x",
(grub_uint16_t) (data->uuid >> 16),
(grub_uint16_t) data->uuid);
for (ptr = *uuid; ptr && *ptr; ptr++)
*ptr = grub_toupper (*ptr);
}
else
*uuid = NULL;
grub_dl_unref (my_mod);
grub_free (data);
return grub_errno;
}
#ifdef GRUB_UTIL
#ifndef MODE_EXFAT
grub_disk_addr_t
grub_fat_get_cluster_sector (grub_disk_t disk, grub_uint64_t *sec_per_lcn)
#else
grub_disk_addr_t
grub_exfat_get_cluster_sector (grub_disk_t disk, grub_uint64_t *sec_per_lcn)
#endif
{
grub_disk_addr_t ret;
struct grub_fat_data *data;
data = grub_fat_mount (disk);
if (!data)
return 0;
ret = data->cluster_sector;
*sec_per_lcn = 1ULL << data->cluster_bits;
grub_free (data);
return ret;
}
#endif
static struct grub_fs grub_fat_fs =
{
#ifdef MODE_EXFAT
.name = "exfat",
#else
.name = "fat",
#endif
.fs_dir = grub_fat_dir,
.fs_open = grub_fat_open,
.fs_read = grub_fat_read,
.fs_close = grub_fat_close,
.fs_label = grub_fat_label,
.fs_uuid = grub_fat_uuid,
#ifdef GRUB_UTIL
#ifdef MODE_EXFAT
/* ExFAT BPB is 30 larger than FAT32 one. */
.reserved_first_sector = 0,
#else
.reserved_first_sector = 1,
#endif
.blocklist_install = 1,
#endif
.next = 0
};
#ifdef MODE_EXFAT
GRUB_MOD_INIT(exfat)
#else
GRUB_MOD_INIT(fat)
#endif
{
COMPILE_TIME_ASSERT (sizeof (struct grub_fat_dir_entry) == 32);
grub_fs_register (&grub_fat_fs);
my_mod = mod;
}
#ifdef MODE_EXFAT
GRUB_MOD_FINI(exfat)
#else
GRUB_MOD_FINI(fat)
#endif
{
grub_fs_unregister (&grub_fat_fs);
}
#ifdef MODE_EXFAT
static int grub_fat_add_chunk(ventoy_img_chunk_list *chunk_list, grub_uint64_t sector, grub_uint64_t size, grub_uint32_t log_sector_size)
{
ventoy_img_chunk *last_chunk;
ventoy_img_chunk *new_chunk;
if (chunk_list->cur_chunk == 0)
{
chunk_list->chunk[0].img_start_sector = 0;
chunk_list->chunk[0].img_end_sector = (size >> 11) - 1;
chunk_list->chunk[0].disk_start_sector = sector;
chunk_list->chunk[0].disk_end_sector = sector + (size >> log_sector_size) - 1;
chunk_list->cur_chunk = 1;
return 0;
}
last_chunk = chunk_list->chunk + chunk_list->cur_chunk - 1;
if (last_chunk->disk_end_sector + 1 == sector)
{
last_chunk->img_end_sector += (size >> 11);
last_chunk->disk_end_sector += (size >> log_sector_size);
return 0;
}
if (chunk_list->cur_chunk == chunk_list->max_chunk)
{
new_chunk = grub_realloc(chunk_list->chunk, chunk_list->max_chunk * 2 * sizeof(ventoy_img_chunk));
if (NULL == new_chunk)
{
return -1;
}
chunk_list->chunk = new_chunk;
chunk_list->max_chunk *= 2;
/* issue: update last_chunk */
last_chunk = chunk_list->chunk + chunk_list->cur_chunk - 1;
}
new_chunk = chunk_list->chunk + chunk_list->cur_chunk;
new_chunk->img_start_sector = last_chunk->img_end_sector + 1;
new_chunk->img_end_sector = new_chunk->img_start_sector + (size >> 11) - 1;
new_chunk->disk_start_sector = sector;
new_chunk->disk_end_sector = sector + (size >> log_sector_size) - 1;
chunk_list->cur_chunk++;
return 0;
}
int grub_fat_get_file_chunk(grub_uint64_t part_start, grub_file_t file, ventoy_img_chunk_list *chunk_list)
{
grub_size_t size;
grub_uint32_t i;
grub_uint32_t logical_cluster;
unsigned logical_cluster_bits;
unsigned long sector;
grub_fshelp_node_t node;
grub_disk_t disk;
grub_uint64_t len;
disk = file->device->disk;
node = file->data;
len = file->size;
if (node->is_contiguous)
{
/* Read the data here. */
sector = (node->data->cluster_sector + ((node->file_cluster - 2) << node->data->cluster_bits));
chunk_list->chunk[0].img_start_sector = 0;
chunk_list->chunk[0].img_end_sector = (file->size >> 11) - 1;
chunk_list->chunk[0].disk_start_sector = sector;
chunk_list->chunk[0].disk_end_sector = sector + (file->size >> disk->log_sector_size) - 1;
chunk_list->cur_chunk = 1;
goto END;
}
/* Calculate the logical cluster number and offset. */
logical_cluster = 0;
logical_cluster_bits = (node->data->cluster_bits + GRUB_DISK_SECTOR_BITS);
if (logical_cluster < node->cur_cluster_num)
{
node->cur_cluster_num = 0;
node->cur_cluster = node->file_cluster;
}
while (len)
{
while (logical_cluster > node->cur_cluster_num)
{
/* Find next cluster. */
grub_uint32_t next_cluster;
grub_uint32_t fat_offset;
switch (node->data->fat_size)
{
case 32:
fat_offset = node->cur_cluster << 2;
break;
case 16:
fat_offset = node->cur_cluster << 1;
break;
default:
/* case 12: */
fat_offset = node->cur_cluster + (node->cur_cluster >> 1);
break;
}
/* Read the FAT. */
if (grub_disk_read (disk, node->data->fat_sector, fat_offset,
(node->data->fat_size + 7) >> 3,
(char *) &next_cluster))
{
return -1;
}
next_cluster = grub_le_to_cpu32 (next_cluster);
switch (node->data->fat_size)
{
case 16:
next_cluster &= 0xFFFF;
break;
case 12:
if (node->cur_cluster & 1)
next_cluster >>= 4;
next_cluster &= 0x0FFF;
break;
}
grub_dprintf ("fat", "fat_size=%d, next_cluster=%u\n", node->data->fat_size, next_cluster);
/* Check the end. */
if (next_cluster >= node->data->cluster_eof_mark)
{
return 0;
}
if (next_cluster < 2 || next_cluster >= node->data->num_clusters)
{
grub_error (GRUB_ERR_BAD_FS, "invalid cluster %u", next_cluster);
return -1;
}
node->cur_cluster = next_cluster;
node->cur_cluster_num++;
}
/* Read the data here. */
sector = (node->data->cluster_sector
+ ((node->cur_cluster - 2)
<< node->data->cluster_bits));
size = (1 << logical_cluster_bits);
if (size > len)
size = len;
grub_fat_add_chunk(chunk_list, sector, size, disk->log_sector_size);
len -= size;
logical_cluster++;
}
END:
for (i = 0; i < chunk_list->cur_chunk; i++)
{
chunk_list->chunk[i].disk_start_sector += part_start;
chunk_list->chunk[i].disk_end_sector += part_start;
}
return 0;
}
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment