1 /******************************************************************************
4 * Copyright (c) 2020, longpanda <admin@ventoy.net>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 3 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include <Library/DebugLib.h>
23 #include <Library/PrintLib.h>
24 #include <Library/UefiLib.h>
25 #include <Library/BaseMemoryLib.h>
26 #include <Library/DevicePathLib.h>
27 #include <Library/MemoryAllocationLib.h>
28 #include <Library/UefiBootServicesTableLib.h>
29 #include <Library/UefiRuntimeServicesTableLib.h>
30 #include <Library/UefiApplicationEntryPoint.h>
31 #include <Protocol/LoadedImage.h>
32 #include <Guid/FileInfo.h>
33 #include <Guid/FileSystemInfo.h>
34 #include <Protocol/BlockIo.h>
35 #include <Protocol/SimpleFileSystem.h>
38 BOOLEAN gDebugPrint
= FALSE
;
39 BOOLEAN gLoadIsoEfi
= FALSE
;
40 ventoy_chain_head
*g_chain
;
41 ventoy_img_chunk
*g_chunk
;
42 UINT32 g_img_chunk_num
;
43 ventoy_override_chunk
*g_override_chunk
;
44 UINT32 g_override_chunk_num
;
45 ventoy_virt_chunk
*g_virt_chunk
;
46 UINT32 g_virt_chunk_num
;
47 vtoy_block_data gBlockData
;
48 ventoy_sector_flag
*g_sector_flag
= NULL
;
49 UINT32 g_sector_flag_num
= 0;
50 static grub_env_get_pf grub_env_get
= NULL
;
52 CONST CHAR16 gIso9660EfiDriverPath
[] = ISO9660_EFI_DRIVER_PATH
;
55 CONST CHAR16
*gEfiBootFileName
[] =
57 EFI_REMOVABLE_MEDIA_FILE_NAME
,
58 L
"\\EFI\\BOOT\\GRUBX64.EFI",
59 L
"\\EFI\\BOOT\\BOOTx64.EFI",
60 L
"\\EFI\\BOOT\\bootx64.efi",
63 /* EFI block device vendor device path GUID */
64 EFI_GUID gVtoyBlockDevicePathGuid
= VTOY_BLOCK_DEVICE_PATH_GUID
;
66 VOID EFIAPI
VtoyDebug(IN CONST CHAR8
*Format
, ...)
71 VA_START (Marker
, Format
);
72 UnicodeVSPrintAsciiFormat(Buffer
, sizeof(Buffer
), Format
, Marker
);
75 gST
->ConOut
->OutputString(gST
->ConOut
, Buffer
);
78 VOID EFIAPI
ventoy_clear_input(VOID
)
82 gST
->ConIn
->Reset(gST
->ConIn
, FALSE
);
83 while (EFI_SUCCESS
== gST
->ConIn
->ReadKeyStroke(gST
->ConIn
, &Key
))
87 gST
->ConIn
->Reset(gST
->ConIn
, FALSE
);
90 static void EFIAPI
ventoy_dump_img_chunk(ventoy_chain_head
*chain
)
95 ventoy_img_chunk
*chunk
;
97 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
99 debug("##################### ventoy_dump_img_chunk #######################");
101 for (i
= 0; i
< chain
->img_chunk_num
; i
++)
103 debug("%2u: [ %u - %u ] <==> [ %llu - %llu ]",
104 i
, chunk
[i
].img_start_sector
, chunk
[i
].img_end_sector
,
105 chunk
[i
].disk_start_sector
, chunk
[i
].disk_end_sector
);
107 if (i
> 0 && (chunk
[i
].img_start_sector
!= chunk
[i
- 1].img_end_sector
+ 1))
112 img_sec
+= chunk
[i
].img_end_sector
- chunk
[i
].img_start_sector
+ 1;
115 if (errcnt
== 0 && (img_sec
* 2048 == g_chain
->real_img_size_in_bytes
))
117 debug("image chunk size check success");
121 debug("image chunk size check failed %d", errcnt
);
124 ventoy_debug_pause();
127 static void EFIAPI
ventoy_dump_override_chunk(ventoy_chain_head
*chain
)
130 ventoy_override_chunk
*chunk
;
132 chunk
= (ventoy_override_chunk
*)((char *)chain
+ chain
->override_chunk_offset
);
134 debug("##################### ventoy_dump_override_chunk #######################");
136 for (i
= 0; i
< g_override_chunk_num
; i
++)
138 debug("%2u: [ %llu, %u ]", i
, chunk
[i
].img_offset
, chunk
[i
].override_size
);
141 ventoy_debug_pause();
144 static void EFIAPI
ventoy_dump_virt_chunk(ventoy_chain_head
*chain
)
147 ventoy_virt_chunk
*node
;
149 debug("##################### ventoy_dump_virt_chunk #######################");
150 debug("virt_chunk_offset=%u", chain
->virt_chunk_offset
);
151 debug("virt_chunk_num=%u", chain
->virt_chunk_num
);
153 node
= (ventoy_virt_chunk
*)((char *)chain
+ chain
->virt_chunk_offset
);
154 for (i
= 0; i
< chain
->virt_chunk_num
; i
++, node
++)
156 debug("%2u: mem:[ %u, %u, %u ] remap:[ %u, %u, %u ]", i
,
157 node
->mem_sector_start
,
158 node
->mem_sector_end
,
159 node
->mem_sector_offset
,
160 node
->remap_sector_start
,
161 node
->remap_sector_end
,
162 node
->org_sector_start
);
165 ventoy_debug_pause();
168 static void EFIAPI
ventoy_dump_chain(ventoy_chain_head
*chain
)
174 guid
= chain
->os_param
.vtoy_disk_guid
;
175 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
177 chksum
+= *((UINT8
*)(&(chain
->os_param
)) + i
);
180 debug("##################### ventoy_dump_chain #######################");
182 debug("os_param->chksum=0x%x (%a)", chain
->os_param
.chksum
, chksum
? "FAILED" : "SUCCESS");
183 debug("os_param->vtoy_disk_guid=%02x%02x%02x%02x", guid
[0], guid
[1], guid
[2], guid
[3]);
184 debug("os_param->vtoy_disk_size=%llu", chain
->os_param
.vtoy_disk_size
);
185 debug("os_param->vtoy_disk_part_id=%u", chain
->os_param
.vtoy_disk_part_id
);
186 debug("os_param->vtoy_disk_part_type=%u", chain
->os_param
.vtoy_disk_part_type
);
187 debug("os_param->vtoy_img_path=<%a>", chain
->os_param
.vtoy_img_path
);
188 debug("os_param->vtoy_img_size=<%llu>", chain
->os_param
.vtoy_img_size
);
189 debug("os_param->vtoy_img_location_addr=<0x%llx>", chain
->os_param
.vtoy_img_location_addr
);
190 debug("os_param->vtoy_img_location_len=<%u>", chain
->os_param
.vtoy_img_location_len
);
192 ventoy_debug_pause();
194 debug("chain->disk_drive=0x%x", chain
->disk_drive
);
195 debug("chain->disk_sector_size=%u", chain
->disk_sector_size
);
196 debug("chain->real_img_size_in_bytes=%llu", chain
->real_img_size_in_bytes
);
197 debug("chain->virt_img_size_in_bytes=%llu", chain
->virt_img_size_in_bytes
);
198 debug("chain->boot_catalog=%u", chain
->boot_catalog
);
199 debug("chain->img_chunk_offset=%u", chain
->img_chunk_offset
);
200 debug("chain->img_chunk_num=%u", chain
->img_chunk_num
);
201 debug("chain->override_chunk_offset=%u", chain
->override_chunk_offset
);
202 debug("chain->override_chunk_num=%u", chain
->override_chunk_num
);
204 ventoy_debug_pause();
206 ventoy_dump_img_chunk(chain
);
207 ventoy_dump_override_chunk(chain
);
208 ventoy_dump_virt_chunk(chain
);
211 EFI_HANDLE EFIAPI
ventoy_get_parent_handle(IN EFI_DEVICE_PATH_PROTOCOL
*pDevPath
)
213 EFI_HANDLE Handle
= NULL
;
214 EFI_STATUS Status
= EFI_SUCCESS
;
215 EFI_DEVICE_PATH_PROTOCOL
*pLastNode
= NULL
;
216 EFI_DEVICE_PATH_PROTOCOL
*pCurNode
= NULL
;
217 EFI_DEVICE_PATH_PROTOCOL
*pTmpDevPath
= NULL
;
219 pTmpDevPath
= DuplicateDevicePath(pDevPath
);
225 pCurNode
= pTmpDevPath
;
226 while (!IsDevicePathEnd(pCurNode
))
228 pLastNode
= pCurNode
;
229 pCurNode
= NextDevicePathNode(pCurNode
);
233 CopyMem(pLastNode
, pCurNode
, sizeof(EFI_DEVICE_PATH_PROTOCOL
));
236 pCurNode
= pTmpDevPath
;
237 Status
= gBS
->LocateDevicePath(&gEfiDevicePathProtocolGuid
, &pCurNode
, &Handle
);
238 debug("Status:%r Parent Handle:%p DP:%s", Status
, Handle
, ConvertDevicePathToText(pTmpDevPath
, FALSE
, FALSE
));
240 FreePool(pTmpDevPath
);
245 EFI_STATUS EFIAPI ventoy_block_io_reset
247 IN EFI_BLOCK_IO_PROTOCOL
*This
,
248 IN BOOLEAN ExtendedVerification
252 (VOID
)ExtendedVerification
;
256 STATIC EFI_STATUS EFIAPI ventoy_read_iso_sector
263 EFI_STATUS Status
= EFI_SUCCESS
;
268 UINT64 ReadStart
= 0;
270 UINT64 OverrideStart
= 0;
271 UINT64 OverrideEnd
= 0;
272 UINT8
*pCurBuf
= (UINT8
*)Buffer
;
273 ventoy_img_chunk
*pchunk
= g_chunk
;
274 ventoy_override_chunk
*pOverride
= g_override_chunk
;
275 EFI_BLOCK_IO_PROTOCOL
*pRawBlockIo
= gBlockData
.pRawBlockIo
;
277 debug("read iso sector %lu count %u", Sector
, Count
);
279 ReadStart
= Sector
* 2048;
280 ReadEnd
= (Sector
+ Count
) * 2048;
282 for (i
= 0; Count
> 0 && i
< g_img_chunk_num
; i
++, pchunk
++)
284 if (Sector
>= pchunk
->img_start_sector
&& Sector
<= pchunk
->img_end_sector
)
286 if (g_chain
->disk_sector_size
== 512)
288 MapLba
= (Sector
- pchunk
->img_start_sector
) * 4 + pchunk
->disk_start_sector
;
292 MapLba
= (Sector
- pchunk
->img_start_sector
) * 2048 / g_chain
->disk_sector_size
+ pchunk
->disk_start_sector
;
295 secLeft
= pchunk
->img_end_sector
+ 1 - Sector
;
296 secRead
= (Count
< secLeft
) ? Count
: secLeft
;
298 Status
= pRawBlockIo
->ReadBlocks(pRawBlockIo
, pRawBlockIo
->Media
->MediaId
,
299 MapLba
, secRead
* 2048, pCurBuf
);
300 if (EFI_ERROR(Status
))
302 debug("Raw disk read block failed %r", Status
);
308 pCurBuf
+= secRead
* 2048;
312 if (ReadStart
> g_chain
->real_img_size_in_bytes
)
318 pCurBuf
= (UINT8
*)Buffer
;
319 for (i
= 0; i
< g_override_chunk_num
; i
++, pOverride
++)
321 OverrideStart
= pOverride
->img_offset
;
322 OverrideEnd
= pOverride
->img_offset
+ pOverride
->override_size
;
324 if (OverrideStart
>= ReadEnd
|| ReadStart
>= OverrideEnd
)
329 if (ReadStart
<= OverrideStart
)
331 if (ReadEnd
<= OverrideEnd
)
333 CopyMem(pCurBuf
+ OverrideStart
- ReadStart
, pOverride
->override_data
, ReadEnd
- OverrideStart
);
337 CopyMem(pCurBuf
+ OverrideStart
- ReadStart
, pOverride
->override_data
, pOverride
->override_size
);
342 if (ReadEnd
<= OverrideEnd
)
344 CopyMem(pCurBuf
, pOverride
->override_data
+ ReadStart
- OverrideStart
, ReadEnd
- ReadStart
);
348 CopyMem(pCurBuf
, pOverride
->override_data
+ ReadStart
- OverrideStart
, OverrideEnd
- ReadStart
);
356 EFI_STATUS EFIAPI ventoy_block_io_read
358 IN EFI_BLOCK_IO_PROTOCOL
*This
,
373 ventoy_sector_flag
*cur_flag
;
374 ventoy_virt_chunk
*node
;
376 //debug("### ventoy_block_io_read sector:%u count:%u", (UINT32)Lba, (UINT32)BufferSize / 2048);
378 secNum
= BufferSize
/ 2048;
381 if (offset
+ BufferSize
< g_chain
->real_img_size_in_bytes
)
383 return ventoy_read_iso_sector(Lba
, secNum
, Buffer
);
386 if (secNum
> g_sector_flag_num
)
388 cur_flag
= AllocatePool(secNum
* sizeof(ventoy_sector_flag
));
389 if (NULL
== cur_flag
)
391 return EFI_OUT_OF_RESOURCES
;
394 FreePool(g_sector_flag
);
395 g_sector_flag
= cur_flag
;
396 g_sector_flag_num
= secNum
;
399 for (curlba
= Lba
, cur_flag
= g_sector_flag
, j
= 0; j
< secNum
; j
++, curlba
++, cur_flag
++)
402 for (node
= g_virt_chunk
, i
= 0; i
< g_virt_chunk_num
; i
++, node
++)
404 if (curlba
>= node
->mem_sector_start
&& curlba
< node
->mem_sector_end
)
406 CopyMem((UINT8
*)Buffer
+ j
* 2048,
407 (char *)g_virt_chunk
+ node
->mem_sector_offset
+ (curlba
- node
->mem_sector_start
) * 2048,
412 else if (curlba
>= node
->remap_sector_start
&& curlba
< node
->remap_sector_end
)
414 cur_flag
->remap_lba
= node
->org_sector_start
+ curlba
- node
->remap_sector_start
;
421 for (curlba
= Lba
, cur_flag
= g_sector_flag
, j
= 0; j
< secNum
; j
++, curlba
++, cur_flag
++)
423 if (cur_flag
->flag
== 2)
427 lastbuffer
= (UINT8
*)Buffer
+ j
* 2048;
428 lastlba
= cur_flag
->remap_lba
;
431 else if (lastlba
+ lbacount
== cur_flag
->remap_lba
)
437 ventoy_read_iso_sector(lastlba
, lbacount
, lastbuffer
);
438 lastbuffer
= (UINT8
*)Buffer
+ j
* 2048;
439 lastlba
= cur_flag
->remap_lba
;
447 ventoy_read_iso_sector(lastlba
, lbacount
, lastbuffer
);
453 EFI_STATUS EFIAPI ventoy_block_io_write
455 IN EFI_BLOCK_IO_PROTOCOL
*This
,
467 return EFI_WRITE_PROTECTED
;
470 EFI_STATUS EFIAPI
ventoy_block_io_flush(IN EFI_BLOCK_IO_PROTOCOL
*This
)
477 EFI_STATUS EFIAPI
ventoy_fill_device_path(VOID
)
480 UINT8 TmpBuf
[128] = {0};
481 VENDOR_DEVICE_PATH
*venPath
= NULL
;
483 venPath
= (VENDOR_DEVICE_PATH
*)TmpBuf
;
484 NameLen
= StrSize(VTOY_BLOCK_DEVICE_PATH_NAME
);
485 venPath
->Header
.Type
= HARDWARE_DEVICE_PATH
;
486 venPath
->Header
.SubType
= HW_VENDOR_DP
;
487 venPath
->Header
.Length
[0] = sizeof(VENDOR_DEVICE_PATH
) + NameLen
;
488 venPath
->Header
.Length
[1] = 0;
489 CopyMem(&venPath
->Guid
, &gVtoyBlockDevicePathGuid
, sizeof(EFI_GUID
));
490 CopyMem(venPath
+ 1, VTOY_BLOCK_DEVICE_PATH_NAME
, NameLen
);
492 gBlockData
.Path
= AppendDevicePathNode(NULL
, (EFI_DEVICE_PATH_PROTOCOL
*)TmpBuf
);
493 gBlockData
.DevicePathCompareLen
= sizeof(VENDOR_DEVICE_PATH
) + NameLen
;
495 debug("gBlockData.Path=<%s>\n", ConvertDevicePathToText(gBlockData
.Path
, FALSE
, FALSE
));
500 EFI_STATUS EFIAPI
ventoy_set_variable(VOID
)
502 EFI_STATUS Status
= EFI_SUCCESS
;
503 EFI_GUID VarGuid
= VENTOY_GUID
;
505 Status
= gRT
->SetVariable(L
"VentoyOsParam", &VarGuid
,
506 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
507 sizeof(g_chain
->os_param
), &(g_chain
->os_param
));
508 debug("set efi variable %r", Status
);
513 EFI_STATUS EFIAPI
ventoy_delete_variable(VOID
)
515 EFI_STATUS Status
= EFI_SUCCESS
;
516 EFI_GUID VarGuid
= VENTOY_GUID
;
518 Status
= gRT
->SetVariable(L
"VentoyOsParam", &VarGuid
,
519 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
521 debug("delete efi variable %r", Status
);
527 EFI_STATUS EFIAPI
ventoy_install_blockio(IN EFI_HANDLE ImageHandle
)
529 EFI_STATUS Status
= EFI_SUCCESS
;
530 EFI_BLOCK_IO_PROTOCOL
*pBlockIo
= &(gBlockData
.BlockIo
);
532 ventoy_fill_device_path();
534 gBlockData
.Media
.BlockSize
= 2048;
535 gBlockData
.Media
.LastBlock
= g_chain
->virt_img_size_in_bytes
/ 2048 - 1;
536 gBlockData
.Media
.ReadOnly
= TRUE
;
537 gBlockData
.Media
.MediaPresent
= 1;
538 gBlockData
.Media
.LogicalBlocksPerPhysicalBlock
= 1;
540 pBlockIo
->Revision
= EFI_BLOCK_IO_PROTOCOL_REVISION3
;
541 pBlockIo
->Media
= &(gBlockData
.Media
);
542 pBlockIo
->Reset
= ventoy_block_io_reset
;
543 pBlockIo
->ReadBlocks
= ventoy_block_io_read
;
544 pBlockIo
->WriteBlocks
= ventoy_block_io_write
;
545 pBlockIo
->FlushBlocks
= ventoy_block_io_flush
;
547 Status
= gBS
->InstallMultipleProtocolInterfaces(&gBlockData
.Handle
,
548 &gEfiBlockIoProtocolGuid
, &gBlockData
.BlockIo
,
549 &gEfiDevicePathProtocolGuid
, gBlockData
.Path
,
552 debug("Install protocol %r", Status
);
554 if (EFI_ERROR(Status
))
559 Status
= gBS
->ConnectController(gBlockData
.Handle
, NULL
, NULL
, 1);
560 debug("Connect controller %r", Status
);
566 EFI_STATUS EFIAPI ventoy_load_image
568 IN EFI_HANDLE ImageHandle
,
569 IN EFI_DEVICE_PATH_PROTOCOL
*pDevicePath
,
570 IN CONST CHAR16
*FileName
,
571 IN UINTN FileNameLen
,
572 OUT EFI_HANDLE
*Image
575 EFI_STATUS Status
= EFI_SUCCESS
;
576 CHAR16 TmpBuf
[256] = {0};
577 FILEPATH_DEVICE_PATH
*pFilePath
= NULL
;
578 EFI_DEVICE_PATH_PROTOCOL
*pImgPath
= NULL
;
580 pFilePath
= (FILEPATH_DEVICE_PATH
*)TmpBuf
;
581 pFilePath
->Header
.Type
= MEDIA_DEVICE_PATH
;
582 pFilePath
->Header
.SubType
= MEDIA_FILEPATH_DP
;
583 pFilePath
->Header
.Length
[0] = FileNameLen
+ sizeof(EFI_DEVICE_PATH_PROTOCOL
);
584 pFilePath
->Header
.Length
[1] = 0;
585 CopyMem(pFilePath
->PathName
, FileName
, FileNameLen
);
587 pImgPath
= AppendDevicePathNode(pDevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)pFilePath
);
590 return EFI_NOT_FOUND
;
593 Status
= gBS
->LoadImage(FALSE
, ImageHandle
, pImgPath
, NULL
, 0, Image
);
595 debug("Load Image File %r DP: <%s>", Status
, ConvertDevicePathToText(pImgPath
, FALSE
, FALSE
));
603 STATIC EFI_STATUS EFIAPI
ventoy_find_iso_disk(IN EFI_HANDLE ImageHandle
)
608 UINT8
*pBuffer
= NULL
;
610 EFI_STATUS Status
= EFI_SUCCESS
;
611 EFI_BLOCK_IO_PROTOCOL
*pBlockIo
;
613 pBuffer
= AllocatePool(2048);
616 return EFI_OUT_OF_RESOURCES
;
619 Status
= gBS
->LocateHandleBuffer(ByProtocol
, &gEfiBlockIoProtocolGuid
,
620 NULL
, &Count
, &Handles
);
621 if (EFI_ERROR(Status
))
627 for (i
= 0; i
< Count
; i
++)
629 Status
= gBS
->HandleProtocol(Handles
[i
], &gEfiBlockIoProtocolGuid
, (VOID
**)&pBlockIo
);
630 if (EFI_ERROR(Status
))
635 DiskSize
= (pBlockIo
->Media
->LastBlock
+ 1) * pBlockIo
->Media
->BlockSize
;
636 debug("This Disk size: %llu", DiskSize
);
637 if (g_chain
->os_param
.vtoy_disk_size
!= DiskSize
)
642 Status
= pBlockIo
->ReadBlocks(pBlockIo
, pBlockIo
->Media
->MediaId
, 0, 512, pBuffer
);
643 if (EFI_ERROR(Status
))
645 debug("ReadBlocks filed %r", Status
);
649 if (CompareMem(g_chain
->os_param
.vtoy_disk_guid
, pBuffer
+ 0x180, 16) == 0)
651 gBlockData
.RawBlockIoHandle
= Handles
[i
];
652 gBlockData
.pRawBlockIo
= pBlockIo
;
653 gBS
->OpenProtocol(Handles
[i
], &gEfiDevicePathProtocolGuid
,
654 (VOID
**)&(gBlockData
.pDiskDevPath
),
657 EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
659 debug("Find Ventoy Disk Handle:%p DP:%s", Handles
[i
],
660 ConvertDevicePathToText(gBlockData
.pDiskDevPath
, FALSE
, FALSE
));
669 return EFI_NOT_FOUND
;
677 STATIC EFI_STATUS EFIAPI
ventoy_find_iso_disk_fs(IN EFI_HANDLE ImageHandle
)
681 EFI_HANDLE Parent
= NULL
;
682 EFI_HANDLE
*Handles
= NULL
;
683 EFI_STATUS Status
= EFI_SUCCESS
;
684 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*pFile
= NULL
;
685 EFI_DEVICE_PATH_PROTOCOL
*pDevPath
= NULL
;
687 Status
= gBS
->LocateHandleBuffer(ByProtocol
, &gEfiSimpleFileSystemProtocolGuid
,
688 NULL
, &Count
, &Handles
);
689 if (EFI_ERROR(Status
))
694 debug("ventoy_find_iso_disk_fs fs count:%u", Count
);
696 for (i
= 0; i
< Count
; i
++)
698 Status
= gBS
->HandleProtocol(Handles
[i
], &gEfiSimpleFileSystemProtocolGuid
, (VOID
**)&pFile
);
699 if (EFI_ERROR(Status
))
704 Status
= gBS
->OpenProtocol(Handles
[i
], &gEfiDevicePathProtocolGuid
,
708 EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
709 if (EFI_ERROR(Status
))
711 debug("Failed to open device path protocol %r", Status
);
715 debug("Handle:%p FS DP: <%s>", Handles
[i
], ConvertDevicePathToText(pDevPath
, FALSE
, FALSE
));
716 Parent
= ventoy_get_parent_handle(pDevPath
);
718 if (Parent
== gBlockData
.RawBlockIoHandle
)
720 debug("Find ventoy disk fs");
721 gBlockData
.DiskFsHandle
= Handles
[i
];
722 gBlockData
.pDiskFs
= pFile
;
723 gBlockData
.pDiskFsDevPath
= pDevPath
;
733 STATIC EFI_STATUS EFIAPI
ventoy_load_isoefi_driver(IN EFI_HANDLE ImageHandle
)
735 EFI_HANDLE Image
= NULL
;
736 EFI_STATUS Status
= EFI_SUCCESS
;
737 CHAR16 LogVar
[4] = L
"5";
739 Status
= ventoy_load_image(ImageHandle
, gBlockData
.pDiskFsDevPath
,
740 gIso9660EfiDriverPath
,
741 sizeof(gIso9660EfiDriverPath
),
743 debug("load iso efi driver status:%r", Status
);
747 gRT
->SetVariable(L
"FS_LOGGING", &gShellVariableGuid
,
748 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
749 sizeof(LogVar
), LogVar
);
752 gRT
->SetVariable(L
"FS_NAME_NOCASE", &gShellVariableGuid
,
753 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
754 sizeof(LogVar
), LogVar
);
756 gBlockData
.IsoDriverImage
= Image
;
757 Status
= gBS
->StartImage(Image
, NULL
, NULL
);
758 debug("Start iso efi driver status:%r", Status
);
763 static int ventoy_update_image_location(ventoy_os_param
*param
)
765 EFI_STATUS Status
= EFI_SUCCESS
;
771 ventoy_image_location
*location
= NULL
;
772 ventoy_image_disk_region
*region
= NULL
;
773 ventoy_img_chunk
*chunk
= g_chunk
;
775 length
= sizeof(ventoy_image_location
) + (g_img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
777 Status
= gBS
->AllocatePool(EfiRuntimeServicesData
, length
+ 4096 * 2, &buffer
);
778 if (EFI_ERROR(Status
) || NULL
== buffer
)
780 debug("Failed to allocate runtime pool %r\n", Status
);
784 address
= (UINTN
)buffer
;
788 address
+= 4096 - (address
% 4096);
792 param
->vtoy_img_location_addr
= address
;
793 param
->vtoy_img_location_len
= length
;
795 /* update check sum */
796 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
798 chksum
+= *((UINT8
*)param
+ i
);
800 param
->chksum
= (chksum
== 0) ? 0 : (UINT8
)(0x100 - chksum
);
802 location
= (ventoy_image_location
*)(unsigned long)(param
->vtoy_img_location_addr
);
803 if (NULL
== location
)
808 CopyMem(&location
->guid
, ¶m
->guid
, sizeof(ventoy_guid
));
809 location
->image_sector_size
= 2048;
810 location
->disk_sector_size
= g_chain
->disk_sector_size
;
811 location
->region_count
= g_img_chunk_num
;
813 region
= location
->regions
;
815 for (i
= 0; i
< g_img_chunk_num
; i
++)
817 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
818 region
->image_start_sector
= chunk
->img_start_sector
;
819 region
->disk_start_sector
= chunk
->disk_start_sector
;
827 STATIC EFI_STATUS EFIAPI
ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle
)
832 CHAR16
*pCmdLine
= NULL
;
833 EFI_STATUS Status
= EFI_SUCCESS
;
834 ventoy_grub_param
*pGrubParam
= NULL
;
835 EFI_LOADED_IMAGE_PROTOCOL
*pImageInfo
= NULL
;
837 Status
= gBS
->HandleProtocol(ImageHandle
, &gEfiLoadedImageProtocolGuid
, (VOID
**)&pImageInfo
);
838 if (EFI_ERROR(Status
))
840 VtoyDebug("Failed to handle load image protocol %r", Status
);
844 pCmdLine
= (CHAR16
*)AllocatePool(pImageInfo
->LoadOptionsSize
+ 4);
845 SetMem(pCmdLine
, pImageInfo
->LoadOptionsSize
+ 4, 0);
846 CopyMem(pCmdLine
, pImageInfo
->LoadOptions
, pImageInfo
->LoadOptionsSize
);
848 if (StrStr(pCmdLine
, L
"debug"))
853 if (StrStr(pCmdLine
, L
"isoefi=on"))
858 debug("cmdline:<%s>", pCmdLine
);
860 pPos
= StrStr(pCmdLine
, L
"env_param=");
863 return EFI_INVALID_PARAMETER
;
866 pGrubParam
= (ventoy_grub_param
*)StrHexToUintn(pPos
+ StrLen(L
"env_param="));
867 grub_env_get
= pGrubParam
->grub_env_get
;
870 pPos
= StrStr(pCmdLine
, L
"mem:");
871 g_chain
= (ventoy_chain_head
*)StrHexToUintn(pPos
+ 4);
873 g_chunk
= (ventoy_img_chunk
*)((char *)g_chain
+ g_chain
->img_chunk_offset
);
874 g_img_chunk_num
= g_chain
->img_chunk_num
;
875 g_override_chunk
= (ventoy_override_chunk
*)((char *)g_chain
+ g_chain
->override_chunk_offset
);
876 g_override_chunk_num
= g_chain
->override_chunk_num
;
877 g_virt_chunk
= (ventoy_virt_chunk
*)((char *)g_chain
+ g_chain
->virt_chunk_offset
);
878 g_virt_chunk_num
= g_chain
->virt_chunk_num
;
880 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
882 chksum
+= *((UINT8
*)(&(g_chain
->os_param
)) + i
);
887 debug("os param checksum: 0x%x %a", g_chain
->os_param
.chksum
, chksum
? "FAILED" : "SUCCESS");
890 ventoy_update_image_location(&(g_chain
->os_param
));
894 ventoy_dump_chain(g_chain
);
901 EFI_STATUS EFIAPI
ventoy_boot(IN EFI_HANDLE ImageHandle
)
907 EFI_HANDLE Image
= NULL
;
908 EFI_HANDLE
*Handles
= NULL
;
909 EFI_STATUS Status
= EFI_SUCCESS
;
910 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*pFile
= NULL
;
911 EFI_DEVICE_PATH_PROTOCOL
*pDevPath
= NULL
;
913 Status
= gBS
->LocateHandleBuffer(ByProtocol
, &gEfiSimpleFileSystemProtocolGuid
,
914 NULL
, &Count
, &Handles
);
915 if (EFI_ERROR(Status
))
920 debug("ventoy_boot fs count:%u", Count
);
922 for (i
= 0; i
< Count
; i
++)
924 Status
= gBS
->HandleProtocol(Handles
[i
], &gEfiSimpleFileSystemProtocolGuid
, (VOID
**)&pFile
);
925 if (EFI_ERROR(Status
))
930 Status
= gBS
->OpenProtocol(Handles
[i
], &gEfiDevicePathProtocolGuid
,
934 EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
935 if (EFI_ERROR(Status
))
937 debug("Failed to open device path protocol %r", Status
);
941 debug("Handle:%p FS DP: <%s>", Handles
[i
], ConvertDevicePathToText(pDevPath
, FALSE
, FALSE
));
942 if (CompareMem(gBlockData
.Path
, pDevPath
, gBlockData
.DevicePathCompareLen
))
944 debug("Not ventoy disk file system");
948 for (j
= 0; j
< ARRAY_SIZE(gEfiBootFileName
); j
++)
950 Status
= ventoy_load_image(ImageHandle
, pDevPath
, gEfiBootFileName
[j
],
951 StrSize(gEfiBootFileName
[j
]), &Image
);
952 if (EFI_SUCCESS
== Status
)
956 debug("Failed to load image %r <%s>", Status
, gEfiBootFileName
[j
]);
959 if (j
>= ARRAY_SIZE(gEfiBootFileName
))
965 debug("Find boot file, now try to boot .....");
966 ventoy_debug_pause();
970 gST
->ConIn
->Reset(gST
->ConIn
, FALSE
);
973 Status
= gBS
->StartImage(Image
, NULL
, NULL
);
974 if (EFI_ERROR(Status
))
976 debug("Failed to start image %r", Status
);
977 gBS
->UnloadImage(Image
);
986 return EFI_NOT_FOUND
;
992 EFI_STATUS EFIAPI
ventoy_clean_env(VOID
)
994 FreePool(g_sector_flag
);
995 g_sector_flag_num
= 0;
997 if (gLoadIsoEfi
&& gBlockData
.IsoDriverImage
)
999 gBS
->UnloadImage(gBlockData
.IsoDriverImage
);
1002 gBS
->DisconnectController(gBlockData
.Handle
, NULL
, NULL
);
1004 gBS
->UninstallMultipleProtocolInterfaces(gBlockData
.Handle
,
1005 &gEfiBlockIoProtocolGuid
, &gBlockData
.BlockIo
,
1006 &gEfiDevicePathProtocolGuid
, gBlockData
.Path
,
1009 ventoy_delete_variable();
1011 if (g_chain
->os_param
.vtoy_img_location_addr
)
1013 FreePool((VOID
*)(UINTN
)g_chain
->os_param
.vtoy_img_location_addr
);
1019 EFI_STATUS EFIAPI VentoyEfiMain
1022 IN EFI_HANDLE ImageHandle
,
1023 IN EFI_SYSTEM_TABLE
*SystemTable
1026 EFI_STATUS Status
= EFI_SUCCESS
;
1028 g_sector_flag_num
= 512; /* initial value */
1030 g_sector_flag
= AllocatePool(g_sector_flag_num
* sizeof(ventoy_sector_flag
));
1031 if (NULL
== g_sector_flag
)
1033 return EFI_OUT_OF_RESOURCES
;
1036 gST
->ConOut
->ClearScreen(gST
->ConOut
);
1037 ventoy_clear_input();
1039 ventoy_parse_cmdline(ImageHandle
);
1040 ventoy_set_variable();
1041 ventoy_find_iso_disk(ImageHandle
);
1045 ventoy_find_iso_disk_fs(ImageHandle
);
1046 ventoy_load_isoefi_driver(ImageHandle
);
1049 ventoy_debug_pause();
1051 ventoy_install_blockio(ImageHandle
);
1053 ventoy_debug_pause();
1055 Status
= ventoy_boot(ImageHandle
);
1056 if (EFI_NOT_FOUND
== Status
)
1058 gST
->ConOut
->OutputString(gST
->ConOut
, L
"No bootfile found for UEFI!\r\n");
1059 gST
->ConOut
->OutputString(gST
->ConOut
, L
"Maybe the image does not support " VENTOY_UEFI_DESC L
"!\r\n");
1065 ventoy_clear_input();
1066 gST
->ConOut
->ClearScreen(gST
->ConOut
);