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/RamDisk.h>
36 #include <Protocol/SimpleFileSystem.h>
39 UINTN g_iso_buf_size
= 0;
40 BOOLEAN gMemdiskMode
= FALSE
;
41 BOOLEAN gDebugPrint
= FALSE
;
42 BOOLEAN gLoadIsoEfi
= FALSE
;
43 ventoy_ram_disk g_ramdisk_param
;
44 ventoy_chain_head
*g_chain
;
45 ventoy_img_chunk
*g_chunk
;
46 UINT32 g_img_chunk_num
;
47 ventoy_override_chunk
*g_override_chunk
;
48 UINT32 g_override_chunk_num
;
49 ventoy_virt_chunk
*g_virt_chunk
;
50 UINT32 g_virt_chunk_num
;
51 vtoy_block_data gBlockData
;
52 ventoy_sector_flag
*g_sector_flag
= NULL
;
53 UINT32 g_sector_flag_num
= 0;
54 static grub_env_get_pf grub_env_get
= NULL
;
56 CONST CHAR16 gIso9660EfiDriverPath
[] = ISO9660_EFI_DRIVER_PATH
;
59 CONST CHAR16
*gEfiBootFileName
[] =
61 EFI_REMOVABLE_MEDIA_FILE_NAME
,
62 L
"\\EFI\\BOOT\\GRUBX64.EFI",
63 L
"\\EFI\\BOOT\\BOOTx64.EFI",
64 L
"\\EFI\\BOOT\\bootx64.efi",
67 /* EFI block device vendor device path GUID */
68 EFI_GUID gVtoyBlockDevicePathGuid
= VTOY_BLOCK_DEVICE_PATH_GUID
;
70 VOID EFIAPI
VtoyDebug(IN CONST CHAR8
*Format
, ...)
75 VA_START (Marker
, Format
);
76 UnicodeVSPrintAsciiFormat(Buffer
, sizeof(Buffer
), Format
, Marker
);
79 gST
->ConOut
->OutputString(gST
->ConOut
, Buffer
);
82 VOID EFIAPI
ventoy_clear_input(VOID
)
86 gST
->ConIn
->Reset(gST
->ConIn
, FALSE
);
87 while (EFI_SUCCESS
== gST
->ConIn
->ReadKeyStroke(gST
->ConIn
, &Key
))
91 gST
->ConIn
->Reset(gST
->ConIn
, FALSE
);
94 static void EFIAPI
ventoy_dump_img_chunk(ventoy_chain_head
*chain
)
99 ventoy_img_chunk
*chunk
;
101 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
103 debug("##################### ventoy_dump_img_chunk #######################");
105 for (i
= 0; i
< chain
->img_chunk_num
; i
++)
107 debug("%2u: [ %u - %u ] <==> [ %llu - %llu ]",
108 i
, chunk
[i
].img_start_sector
, chunk
[i
].img_end_sector
,
109 chunk
[i
].disk_start_sector
, chunk
[i
].disk_end_sector
);
111 if (i
> 0 && (chunk
[i
].img_start_sector
!= chunk
[i
- 1].img_end_sector
+ 1))
116 img_sec
+= chunk
[i
].img_end_sector
- chunk
[i
].img_start_sector
+ 1;
119 if (errcnt
== 0 && (img_sec
* 2048 == g_chain
->real_img_size_in_bytes
))
121 debug("image chunk size check success");
125 debug("image chunk size check failed %d", errcnt
);
128 ventoy_debug_pause();
131 static void EFIAPI
ventoy_dump_override_chunk(ventoy_chain_head
*chain
)
134 ventoy_override_chunk
*chunk
;
136 chunk
= (ventoy_override_chunk
*)((char *)chain
+ chain
->override_chunk_offset
);
138 debug("##################### ventoy_dump_override_chunk #######################");
140 for (i
= 0; i
< g_override_chunk_num
; i
++)
142 debug("%2u: [ %llu, %u ]", i
, chunk
[i
].img_offset
, chunk
[i
].override_size
);
145 ventoy_debug_pause();
148 static void EFIAPI
ventoy_dump_virt_chunk(ventoy_chain_head
*chain
)
151 ventoy_virt_chunk
*node
;
153 debug("##################### ventoy_dump_virt_chunk #######################");
154 debug("virt_chunk_offset=%u", chain
->virt_chunk_offset
);
155 debug("virt_chunk_num=%u", chain
->virt_chunk_num
);
157 node
= (ventoy_virt_chunk
*)((char *)chain
+ chain
->virt_chunk_offset
);
158 for (i
= 0; i
< chain
->virt_chunk_num
; i
++, node
++)
160 debug("%2u: mem:[ %u, %u, %u ] remap:[ %u, %u, %u ]", i
,
161 node
->mem_sector_start
,
162 node
->mem_sector_end
,
163 node
->mem_sector_offset
,
164 node
->remap_sector_start
,
165 node
->remap_sector_end
,
166 node
->org_sector_start
);
169 ventoy_debug_pause();
172 static void EFIAPI
ventoy_dump_chain(ventoy_chain_head
*chain
)
178 guid
= chain
->os_param
.vtoy_disk_guid
;
179 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
181 chksum
+= *((UINT8
*)(&(chain
->os_param
)) + i
);
184 debug("##################### ventoy_dump_chain #######################");
186 debug("os_param->chksum=0x%x (%a)", chain
->os_param
.chksum
, chksum
? "FAILED" : "SUCCESS");
187 debug("os_param->vtoy_disk_guid=%02x%02x%02x%02x", guid
[0], guid
[1], guid
[2], guid
[3]);
188 debug("os_param->vtoy_disk_size=%llu", chain
->os_param
.vtoy_disk_size
);
189 debug("os_param->vtoy_disk_part_id=%u", chain
->os_param
.vtoy_disk_part_id
);
190 debug("os_param->vtoy_disk_part_type=%u", chain
->os_param
.vtoy_disk_part_type
);
191 debug("os_param->vtoy_img_path=<%a>", chain
->os_param
.vtoy_img_path
);
192 debug("os_param->vtoy_img_size=<%llu>", chain
->os_param
.vtoy_img_size
);
193 debug("os_param->vtoy_img_location_addr=<0x%llx>", chain
->os_param
.vtoy_img_location_addr
);
194 debug("os_param->vtoy_img_location_len=<%u>", chain
->os_param
.vtoy_img_location_len
);
196 ventoy_debug_pause();
198 debug("chain->disk_drive=0x%x", chain
->disk_drive
);
199 debug("chain->disk_sector_size=%u", chain
->disk_sector_size
);
200 debug("chain->real_img_size_in_bytes=%llu", chain
->real_img_size_in_bytes
);
201 debug("chain->virt_img_size_in_bytes=%llu", chain
->virt_img_size_in_bytes
);
202 debug("chain->boot_catalog=%u", chain
->boot_catalog
);
203 debug("chain->img_chunk_offset=%u", chain
->img_chunk_offset
);
204 debug("chain->img_chunk_num=%u", chain
->img_chunk_num
);
205 debug("chain->override_chunk_offset=%u", chain
->override_chunk_offset
);
206 debug("chain->override_chunk_num=%u", chain
->override_chunk_num
);
208 ventoy_debug_pause();
210 ventoy_dump_img_chunk(chain
);
211 ventoy_dump_override_chunk(chain
);
212 ventoy_dump_virt_chunk(chain
);
215 EFI_HANDLE EFIAPI
ventoy_get_parent_handle(IN EFI_DEVICE_PATH_PROTOCOL
*pDevPath
)
217 EFI_HANDLE Handle
= NULL
;
218 EFI_STATUS Status
= EFI_SUCCESS
;
219 EFI_DEVICE_PATH_PROTOCOL
*pLastNode
= NULL
;
220 EFI_DEVICE_PATH_PROTOCOL
*pCurNode
= NULL
;
221 EFI_DEVICE_PATH_PROTOCOL
*pTmpDevPath
= NULL
;
223 pTmpDevPath
= DuplicateDevicePath(pDevPath
);
229 pCurNode
= pTmpDevPath
;
230 while (!IsDevicePathEnd(pCurNode
))
232 pLastNode
= pCurNode
;
233 pCurNode
= NextDevicePathNode(pCurNode
);
237 CopyMem(pLastNode
, pCurNode
, sizeof(EFI_DEVICE_PATH_PROTOCOL
));
240 pCurNode
= pTmpDevPath
;
241 Status
= gBS
->LocateDevicePath(&gEfiDevicePathProtocolGuid
, &pCurNode
, &Handle
);
242 debug("Status:%r Parent Handle:%p DP:%s", Status
, Handle
, ConvertDevicePathToText(pTmpDevPath
, FALSE
, FALSE
));
244 FreePool(pTmpDevPath
);
249 EFI_STATUS EFIAPI ventoy_block_io_reset
251 IN EFI_BLOCK_IO_PROTOCOL
*This
,
252 IN BOOLEAN ExtendedVerification
256 (VOID
)ExtendedVerification
;
260 STATIC EFI_STATUS EFIAPI ventoy_read_iso_sector
267 EFI_STATUS Status
= EFI_SUCCESS
;
272 UINT64 ReadStart
= 0;
274 UINT64 OverrideStart
= 0;
275 UINT64 OverrideEnd
= 0;
276 UINT8
*pCurBuf
= (UINT8
*)Buffer
;
277 ventoy_img_chunk
*pchunk
= g_chunk
;
278 ventoy_override_chunk
*pOverride
= g_override_chunk
;
279 EFI_BLOCK_IO_PROTOCOL
*pRawBlockIo
= gBlockData
.pRawBlockIo
;
281 debug("read iso sector %lu count %u", Sector
, Count
);
283 ReadStart
= Sector
* 2048;
284 ReadEnd
= (Sector
+ Count
) * 2048;
286 for (i
= 0; Count
> 0 && i
< g_img_chunk_num
; i
++, pchunk
++)
288 if (Sector
>= pchunk
->img_start_sector
&& Sector
<= pchunk
->img_end_sector
)
290 if (g_chain
->disk_sector_size
== 512)
292 MapLba
= (Sector
- pchunk
->img_start_sector
) * 4 + pchunk
->disk_start_sector
;
296 MapLba
= (Sector
- pchunk
->img_start_sector
) * 2048 / g_chain
->disk_sector_size
+ pchunk
->disk_start_sector
;
299 secLeft
= pchunk
->img_end_sector
+ 1 - Sector
;
300 secRead
= (Count
< secLeft
) ? Count
: secLeft
;
302 Status
= pRawBlockIo
->ReadBlocks(pRawBlockIo
, pRawBlockIo
->Media
->MediaId
,
303 MapLba
, secRead
* 2048, pCurBuf
);
304 if (EFI_ERROR(Status
))
306 debug("Raw disk read block failed %r", Status
);
312 pCurBuf
+= secRead
* 2048;
316 if (ReadStart
> g_chain
->real_img_size_in_bytes
)
322 pCurBuf
= (UINT8
*)Buffer
;
323 for (i
= 0; i
< g_override_chunk_num
; i
++, pOverride
++)
325 OverrideStart
= pOverride
->img_offset
;
326 OverrideEnd
= pOverride
->img_offset
+ pOverride
->override_size
;
328 if (OverrideStart
>= ReadEnd
|| ReadStart
>= OverrideEnd
)
333 if (ReadStart
<= OverrideStart
)
335 if (ReadEnd
<= OverrideEnd
)
337 CopyMem(pCurBuf
+ OverrideStart
- ReadStart
, pOverride
->override_data
, ReadEnd
- OverrideStart
);
341 CopyMem(pCurBuf
+ OverrideStart
- ReadStart
, pOverride
->override_data
, pOverride
->override_size
);
346 if (ReadEnd
<= OverrideEnd
)
348 CopyMem(pCurBuf
, pOverride
->override_data
+ ReadStart
- OverrideStart
, ReadEnd
- ReadStart
);
352 CopyMem(pCurBuf
, pOverride
->override_data
+ ReadStart
- OverrideStart
, OverrideEnd
- ReadStart
);
360 EFI_STATUS EFIAPI ventoy_block_io_ramdisk_read
362 IN EFI_BLOCK_IO_PROTOCOL
*This
,
369 //debug("### ventoy_block_io_ramdisk_read sector:%u count:%u", (UINT32)Lba, (UINT32)BufferSize / 2048);
374 CopyMem(Buffer
, (char *)g_chain
+ (Lba
* 2048), BufferSize
);
379 EFI_STATUS EFIAPI ventoy_block_io_read
381 IN EFI_BLOCK_IO_PROTOCOL
*This
,
396 ventoy_sector_flag
*cur_flag
;
397 ventoy_virt_chunk
*node
;
399 //debug("### ventoy_block_io_read sector:%u count:%u", (UINT32)Lba, (UINT32)BufferSize / 2048);
401 secNum
= BufferSize
/ 2048;
404 if (offset
+ BufferSize
< g_chain
->real_img_size_in_bytes
)
406 return ventoy_read_iso_sector(Lba
, secNum
, Buffer
);
409 if (secNum
> g_sector_flag_num
)
411 cur_flag
= AllocatePool(secNum
* sizeof(ventoy_sector_flag
));
412 if (NULL
== cur_flag
)
414 return EFI_OUT_OF_RESOURCES
;
417 FreePool(g_sector_flag
);
418 g_sector_flag
= cur_flag
;
419 g_sector_flag_num
= secNum
;
422 for (curlba
= Lba
, cur_flag
= g_sector_flag
, j
= 0; j
< secNum
; j
++, curlba
++, cur_flag
++)
425 for (node
= g_virt_chunk
, i
= 0; i
< g_virt_chunk_num
; i
++, node
++)
427 if (curlba
>= node
->mem_sector_start
&& curlba
< node
->mem_sector_end
)
429 CopyMem((UINT8
*)Buffer
+ j
* 2048,
430 (char *)g_virt_chunk
+ node
->mem_sector_offset
+ (curlba
- node
->mem_sector_start
) * 2048,
435 else if (curlba
>= node
->remap_sector_start
&& curlba
< node
->remap_sector_end
)
437 cur_flag
->remap_lba
= node
->org_sector_start
+ curlba
- node
->remap_sector_start
;
444 for (curlba
= Lba
, cur_flag
= g_sector_flag
, j
= 0; j
< secNum
; j
++, curlba
++, cur_flag
++)
446 if (cur_flag
->flag
== 2)
450 lastbuffer
= (UINT8
*)Buffer
+ j
* 2048;
451 lastlba
= cur_flag
->remap_lba
;
454 else if (lastlba
+ lbacount
== cur_flag
->remap_lba
)
460 ventoy_read_iso_sector(lastlba
, lbacount
, lastbuffer
);
461 lastbuffer
= (UINT8
*)Buffer
+ j
* 2048;
462 lastlba
= cur_flag
->remap_lba
;
470 ventoy_read_iso_sector(lastlba
, lbacount
, lastbuffer
);
476 EFI_STATUS EFIAPI ventoy_block_io_write
478 IN EFI_BLOCK_IO_PROTOCOL
*This
,
490 return EFI_WRITE_PROTECTED
;
493 EFI_STATUS EFIAPI
ventoy_block_io_flush(IN EFI_BLOCK_IO_PROTOCOL
*This
)
500 EFI_STATUS EFIAPI
ventoy_fill_device_path(VOID
)
503 UINT8 TmpBuf
[128] = {0};
504 VENDOR_DEVICE_PATH
*venPath
= NULL
;
506 venPath
= (VENDOR_DEVICE_PATH
*)TmpBuf
;
507 NameLen
= StrSize(VTOY_BLOCK_DEVICE_PATH_NAME
);
508 venPath
->Header
.Type
= HARDWARE_DEVICE_PATH
;
509 venPath
->Header
.SubType
= HW_VENDOR_DP
;
510 venPath
->Header
.Length
[0] = sizeof(VENDOR_DEVICE_PATH
) + NameLen
;
511 venPath
->Header
.Length
[1] = 0;
512 CopyMem(&venPath
->Guid
, &gVtoyBlockDevicePathGuid
, sizeof(EFI_GUID
));
513 CopyMem(venPath
+ 1, VTOY_BLOCK_DEVICE_PATH_NAME
, NameLen
);
515 gBlockData
.Path
= AppendDevicePathNode(NULL
, (EFI_DEVICE_PATH_PROTOCOL
*)TmpBuf
);
516 gBlockData
.DevicePathCompareLen
= sizeof(VENDOR_DEVICE_PATH
) + NameLen
;
518 debug("gBlockData.Path=<%s>\n", ConvertDevicePathToText(gBlockData
.Path
, FALSE
, FALSE
));
523 EFI_STATUS EFIAPI
ventoy_save_ramdisk_param(VOID
)
525 EFI_STATUS Status
= EFI_SUCCESS
;
526 EFI_GUID VarGuid
= VENTOY_GUID
;
528 Status
= gRT
->SetVariable(L
"VentoyRamDisk", &VarGuid
,
529 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
530 sizeof(g_ramdisk_param
), &(g_ramdisk_param
));
531 debug("set efi variable %r", Status
);
536 EFI_STATUS EFIAPI
ventoy_del_ramdisk_param(VOID
)
538 EFI_STATUS Status
= EFI_SUCCESS
;
539 EFI_GUID VarGuid
= VENTOY_GUID
;
541 Status
= gRT
->SetVariable(L
"VentoyRamDisk", &VarGuid
,
542 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
544 debug("delete efi variable %r", Status
);
550 EFI_STATUS EFIAPI
ventoy_set_variable(VOID
)
552 EFI_STATUS Status
= EFI_SUCCESS
;
553 EFI_GUID VarGuid
= VENTOY_GUID
;
555 Status
= gRT
->SetVariable(L
"VentoyOsParam", &VarGuid
,
556 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
557 sizeof(g_chain
->os_param
), &(g_chain
->os_param
));
558 debug("set efi variable %r", Status
);
563 EFI_STATUS EFIAPI
ventoy_delete_variable(VOID
)
565 EFI_STATUS Status
= EFI_SUCCESS
;
566 EFI_GUID VarGuid
= VENTOY_GUID
;
568 Status
= gRT
->SetVariable(L
"VentoyOsParam", &VarGuid
,
569 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
571 debug("delete efi variable %r", Status
);
577 EFI_STATUS EFIAPI
ventoy_install_blockio(IN EFI_HANDLE ImageHandle
, IN UINT64 ImgSize
)
579 EFI_STATUS Status
= EFI_SUCCESS
;
580 EFI_BLOCK_IO_PROTOCOL
*pBlockIo
= &(gBlockData
.BlockIo
);
582 ventoy_fill_device_path();
584 gBlockData
.Media
.BlockSize
= 2048;
585 gBlockData
.Media
.LastBlock
= ImgSize
/ 2048 - 1;
586 gBlockData
.Media
.ReadOnly
= TRUE
;
587 gBlockData
.Media
.MediaPresent
= 1;
588 gBlockData
.Media
.LogicalBlocksPerPhysicalBlock
= 1;
590 pBlockIo
->Revision
= EFI_BLOCK_IO_PROTOCOL_REVISION3
;
591 pBlockIo
->Media
= &(gBlockData
.Media
);
592 pBlockIo
->Reset
= ventoy_block_io_reset
;
596 pBlockIo
->ReadBlocks
= ventoy_block_io_ramdisk_read
;
600 pBlockIo
->ReadBlocks
= ventoy_block_io_read
;
603 pBlockIo
->WriteBlocks
= ventoy_block_io_write
;
604 pBlockIo
->FlushBlocks
= ventoy_block_io_flush
;
606 Status
= gBS
->InstallMultipleProtocolInterfaces(&gBlockData
.Handle
,
607 &gEfiBlockIoProtocolGuid
, &gBlockData
.BlockIo
,
608 &gEfiDevicePathProtocolGuid
, gBlockData
.Path
,
611 debug("Install protocol %r", Status
);
613 if (EFI_ERROR(Status
))
618 Status
= gBS
->ConnectController(gBlockData
.Handle
, NULL
, NULL
, 1);
619 debug("Connect controller %r", Status
);
625 EFI_STATUS EFIAPI ventoy_load_image
627 IN EFI_HANDLE ImageHandle
,
628 IN EFI_DEVICE_PATH_PROTOCOL
*pDevicePath
,
629 IN CONST CHAR16
*FileName
,
630 IN UINTN FileNameLen
,
631 OUT EFI_HANDLE
*Image
634 EFI_STATUS Status
= EFI_SUCCESS
;
635 CHAR16 TmpBuf
[256] = {0};
636 FILEPATH_DEVICE_PATH
*pFilePath
= NULL
;
637 EFI_DEVICE_PATH_PROTOCOL
*pImgPath
= NULL
;
639 pFilePath
= (FILEPATH_DEVICE_PATH
*)TmpBuf
;
640 pFilePath
->Header
.Type
= MEDIA_DEVICE_PATH
;
641 pFilePath
->Header
.SubType
= MEDIA_FILEPATH_DP
;
642 pFilePath
->Header
.Length
[0] = FileNameLen
+ sizeof(EFI_DEVICE_PATH_PROTOCOL
);
643 pFilePath
->Header
.Length
[1] = 0;
644 CopyMem(pFilePath
->PathName
, FileName
, FileNameLen
);
646 pImgPath
= AppendDevicePathNode(pDevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)pFilePath
);
649 return EFI_NOT_FOUND
;
652 Status
= gBS
->LoadImage(FALSE
, ImageHandle
, pImgPath
, NULL
, 0, Image
);
654 debug("Load Image File %r DP: <%s>", Status
, ConvertDevicePathToText(pImgPath
, FALSE
, FALSE
));
662 STATIC EFI_STATUS EFIAPI
ventoy_find_iso_disk(IN EFI_HANDLE ImageHandle
)
667 UINT8
*pBuffer
= NULL
;
669 EFI_STATUS Status
= EFI_SUCCESS
;
670 EFI_BLOCK_IO_PROTOCOL
*pBlockIo
;
672 pBuffer
= AllocatePool(2048);
675 return EFI_OUT_OF_RESOURCES
;
678 Status
= gBS
->LocateHandleBuffer(ByProtocol
, &gEfiBlockIoProtocolGuid
,
679 NULL
, &Count
, &Handles
);
680 if (EFI_ERROR(Status
))
686 for (i
= 0; i
< Count
; i
++)
688 Status
= gBS
->HandleProtocol(Handles
[i
], &gEfiBlockIoProtocolGuid
, (VOID
**)&pBlockIo
);
689 if (EFI_ERROR(Status
))
694 DiskSize
= (pBlockIo
->Media
->LastBlock
+ 1) * pBlockIo
->Media
->BlockSize
;
695 debug("This Disk size: %llu", DiskSize
);
696 if (g_chain
->os_param
.vtoy_disk_size
!= DiskSize
)
701 Status
= pBlockIo
->ReadBlocks(pBlockIo
, pBlockIo
->Media
->MediaId
, 0, 512, pBuffer
);
702 if (EFI_ERROR(Status
))
704 debug("ReadBlocks filed %r", Status
);
708 if (CompareMem(g_chain
->os_param
.vtoy_disk_guid
, pBuffer
+ 0x180, 16) == 0)
710 gBlockData
.RawBlockIoHandle
= Handles
[i
];
711 gBlockData
.pRawBlockIo
= pBlockIo
;
712 gBS
->OpenProtocol(Handles
[i
], &gEfiDevicePathProtocolGuid
,
713 (VOID
**)&(gBlockData
.pDiskDevPath
),
716 EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
718 debug("Find Ventoy Disk Handle:%p DP:%s", Handles
[i
],
719 ConvertDevicePathToText(gBlockData
.pDiskDevPath
, FALSE
, FALSE
));
728 return EFI_NOT_FOUND
;
736 STATIC EFI_STATUS EFIAPI
ventoy_find_iso_disk_fs(IN EFI_HANDLE ImageHandle
)
740 EFI_HANDLE Parent
= NULL
;
741 EFI_HANDLE
*Handles
= NULL
;
742 EFI_STATUS Status
= EFI_SUCCESS
;
743 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*pFile
= NULL
;
744 EFI_DEVICE_PATH_PROTOCOL
*pDevPath
= NULL
;
746 Status
= gBS
->LocateHandleBuffer(ByProtocol
, &gEfiSimpleFileSystemProtocolGuid
,
747 NULL
, &Count
, &Handles
);
748 if (EFI_ERROR(Status
))
753 debug("ventoy_find_iso_disk_fs fs count:%u", Count
);
755 for (i
= 0; i
< Count
; i
++)
757 Status
= gBS
->HandleProtocol(Handles
[i
], &gEfiSimpleFileSystemProtocolGuid
, (VOID
**)&pFile
);
758 if (EFI_ERROR(Status
))
763 Status
= gBS
->OpenProtocol(Handles
[i
], &gEfiDevicePathProtocolGuid
,
767 EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
768 if (EFI_ERROR(Status
))
770 debug("Failed to open device path protocol %r", Status
);
774 debug("Handle:%p FS DP: <%s>", Handles
[i
], ConvertDevicePathToText(pDevPath
, FALSE
, FALSE
));
775 Parent
= ventoy_get_parent_handle(pDevPath
);
777 if (Parent
== gBlockData
.RawBlockIoHandle
)
779 debug("Find ventoy disk fs");
780 gBlockData
.DiskFsHandle
= Handles
[i
];
781 gBlockData
.pDiskFs
= pFile
;
782 gBlockData
.pDiskFsDevPath
= pDevPath
;
792 STATIC EFI_STATUS EFIAPI
ventoy_load_isoefi_driver(IN EFI_HANDLE ImageHandle
)
794 EFI_HANDLE Image
= NULL
;
795 EFI_STATUS Status
= EFI_SUCCESS
;
796 CHAR16 LogVar
[4] = L
"5";
798 Status
= ventoy_load_image(ImageHandle
, gBlockData
.pDiskFsDevPath
,
799 gIso9660EfiDriverPath
,
800 sizeof(gIso9660EfiDriverPath
),
802 debug("load iso efi driver status:%r", Status
);
806 gRT
->SetVariable(L
"FS_LOGGING", &gShellVariableGuid
,
807 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
808 sizeof(LogVar
), LogVar
);
811 gRT
->SetVariable(L
"FS_NAME_NOCASE", &gShellVariableGuid
,
812 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
813 sizeof(LogVar
), LogVar
);
815 gBlockData
.IsoDriverImage
= Image
;
816 Status
= gBS
->StartImage(Image
, NULL
, NULL
);
817 debug("Start iso efi driver status:%r", Status
);
822 static int ventoy_update_image_location(ventoy_os_param
*param
)
824 EFI_STATUS Status
= EFI_SUCCESS
;
830 ventoy_image_location
*location
= NULL
;
831 ventoy_image_disk_region
*region
= NULL
;
832 ventoy_img_chunk
*chunk
= g_chunk
;
834 length
= sizeof(ventoy_image_location
) + (g_img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
836 Status
= gBS
->AllocatePool(EfiRuntimeServicesData
, length
+ 4096 * 2, &buffer
);
837 if (EFI_ERROR(Status
) || NULL
== buffer
)
839 debug("Failed to allocate runtime pool %r\n", Status
);
843 address
= (UINTN
)buffer
;
847 address
+= 4096 - (address
% 4096);
851 param
->vtoy_img_location_addr
= address
;
852 param
->vtoy_img_location_len
= length
;
854 /* update check sum */
855 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
857 chksum
+= *((UINT8
*)param
+ i
);
859 param
->chksum
= (chksum
== 0) ? 0 : (UINT8
)(0x100 - chksum
);
861 location
= (ventoy_image_location
*)(unsigned long)(param
->vtoy_img_location_addr
);
862 if (NULL
== location
)
867 CopyMem(&location
->guid
, ¶m
->guid
, sizeof(ventoy_guid
));
868 location
->image_sector_size
= 2048;
869 location
->disk_sector_size
= g_chain
->disk_sector_size
;
870 location
->region_count
= g_img_chunk_num
;
872 region
= location
->regions
;
874 for (i
= 0; i
< g_img_chunk_num
; i
++)
876 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
877 region
->image_start_sector
= chunk
->img_start_sector
;
878 region
->disk_start_sector
= chunk
->disk_start_sector
;
886 STATIC EFI_STATUS EFIAPI
ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle
)
892 CHAR16
*pCmdLine
= NULL
;
893 EFI_STATUS Status
= EFI_SUCCESS
;
894 ventoy_grub_param
*pGrubParam
= NULL
;
895 EFI_LOADED_IMAGE_PROTOCOL
*pImageInfo
= NULL
;
897 Status
= gBS
->HandleProtocol(ImageHandle
, &gEfiLoadedImageProtocolGuid
, (VOID
**)&pImageInfo
);
898 if (EFI_ERROR(Status
))
900 VtoyDebug("Failed to handle load image protocol %r", Status
);
904 pCmdLine
= (CHAR16
*)AllocatePool(pImageInfo
->LoadOptionsSize
+ 4);
905 SetMem(pCmdLine
, pImageInfo
->LoadOptionsSize
+ 4, 0);
906 CopyMem(pCmdLine
, pImageInfo
->LoadOptions
, pImageInfo
->LoadOptionsSize
);
908 if (StrStr(pCmdLine
, L
"debug"))
913 if (StrStr(pCmdLine
, L
"isoefi=on"))
918 debug("cmdline:<%s>", pCmdLine
);
920 pPos
= StrStr(pCmdLine
, L
"env_param=");
923 return EFI_INVALID_PARAMETER
;
926 pGrubParam
= (ventoy_grub_param
*)StrHexToUintn(pPos
+ StrLen(L
"env_param="));
927 grub_env_get
= pGrubParam
->grub_env_get
;
929 pPos
= StrStr(pCmdLine
, L
"mem:");
930 g_chain
= (ventoy_chain_head
*)StrHexToUintn(pPos
+ 4);
932 pPos
= StrStr(pPos
, L
"size:");
933 size
= StrDecimalToUintn(pPos
+ 5);
935 debug("memory addr:%p size:%lu", g_chain
, size
);
937 if (StrStr(pCmdLine
, L
"memdisk"))
939 g_iso_buf_size
= size
;
944 g_chunk
= (ventoy_img_chunk
*)((char *)g_chain
+ g_chain
->img_chunk_offset
);
945 g_img_chunk_num
= g_chain
->img_chunk_num
;
946 g_override_chunk
= (ventoy_override_chunk
*)((char *)g_chain
+ g_chain
->override_chunk_offset
);
947 g_override_chunk_num
= g_chain
->override_chunk_num
;
948 g_virt_chunk
= (ventoy_virt_chunk
*)((char *)g_chain
+ g_chain
->virt_chunk_offset
);
949 g_virt_chunk_num
= g_chain
->virt_chunk_num
;
951 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
953 chksum
+= *((UINT8
*)(&(g_chain
->os_param
)) + i
);
958 debug("os param checksum: 0x%x %a", g_chain
->os_param
.chksum
, chksum
? "FAILED" : "SUCCESS");
961 ventoy_update_image_location(&(g_chain
->os_param
));
965 ventoy_dump_chain(g_chain
);
973 EFI_STATUS EFIAPI
ventoy_boot(IN EFI_HANDLE ImageHandle
)
979 EFI_HANDLE Image
= NULL
;
980 EFI_HANDLE
*Handles
= NULL
;
981 EFI_STATUS Status
= EFI_SUCCESS
;
982 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*pFile
= NULL
;
983 EFI_DEVICE_PATH_PROTOCOL
*pDevPath
= NULL
;
985 Status
= gBS
->LocateHandleBuffer(ByProtocol
, &gEfiSimpleFileSystemProtocolGuid
,
986 NULL
, &Count
, &Handles
);
987 if (EFI_ERROR(Status
))
992 debug("ventoy_boot fs count:%u", Count
);
994 for (i
= 0; i
< Count
; i
++)
996 Status
= gBS
->HandleProtocol(Handles
[i
], &gEfiSimpleFileSystemProtocolGuid
, (VOID
**)&pFile
);
997 if (EFI_ERROR(Status
))
1002 Status
= gBS
->OpenProtocol(Handles
[i
], &gEfiDevicePathProtocolGuid
,
1006 EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
1007 if (EFI_ERROR(Status
))
1009 debug("Failed to open device path protocol %r", Status
);
1013 debug("Handle:%p FS DP: <%s>", Handles
[i
], ConvertDevicePathToText(pDevPath
, FALSE
, FALSE
));
1014 if (CompareMem(gBlockData
.Path
, pDevPath
, gBlockData
.DevicePathCompareLen
))
1016 debug("Not ventoy disk file system");
1020 for (j
= 0; j
< ARRAY_SIZE(gEfiBootFileName
); j
++)
1022 Status
= ventoy_load_image(ImageHandle
, pDevPath
, gEfiBootFileName
[j
],
1023 StrSize(gEfiBootFileName
[j
]), &Image
);
1024 if (EFI_SUCCESS
== Status
)
1028 debug("Failed to load image %r <%s>", Status
, gEfiBootFileName
[j
]);
1031 if (j
>= ARRAY_SIZE(gEfiBootFileName
))
1037 debug("Find boot file, now try to boot .....");
1038 ventoy_debug_pause();
1042 gST
->ConIn
->Reset(gST
->ConIn
, FALSE
);
1045 Status
= gBS
->StartImage(Image
, NULL
, NULL
);
1046 if (EFI_ERROR(Status
))
1048 debug("Failed to start image %r", Status
);
1050 gBS
->UnloadImage(Image
);
1059 return EFI_NOT_FOUND
;
1065 EFI_STATUS EFIAPI
ventoy_clean_env(VOID
)
1067 FreePool(g_sector_flag
);
1068 g_sector_flag_num
= 0;
1070 if (gLoadIsoEfi
&& gBlockData
.IsoDriverImage
)
1072 gBS
->UnloadImage(gBlockData
.IsoDriverImage
);
1075 gBS
->DisconnectController(gBlockData
.Handle
, NULL
, NULL
);
1077 gBS
->UninstallMultipleProtocolInterfaces(gBlockData
.Handle
,
1078 &gEfiBlockIoProtocolGuid
, &gBlockData
.BlockIo
,
1079 &gEfiDevicePathProtocolGuid
, gBlockData
.Path
,
1082 ventoy_delete_variable();
1084 if (g_chain
->os_param
.vtoy_img_location_addr
)
1086 FreePool((VOID
*)(UINTN
)g_chain
->os_param
.vtoy_img_location_addr
);
1092 EFI_STATUS EFIAPI
ventoy_ramdisk_boot(IN EFI_HANDLE ImageHandle
)
1094 EFI_STATUS Status
= EFI_SUCCESS
;
1095 EFI_RAM_DISK_PROTOCOL
*RamDisk
= NULL
;
1096 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
= NULL
;
1098 debug("RamDisk Boot ...");
1100 Status
= gBS
->LocateProtocol(&gEfiRamDiskProtocolGuid
, NULL
, (VOID
**)&RamDisk
);
1101 if (EFI_ERROR(Status
))
1103 debug("Failed to locate ramdisk protocol %r", Status
);
1106 debug("Locate RamDisk Protocol %r ...", Status
);
1108 Status
= RamDisk
->Register((UINTN
)g_chain
, (UINT64
)g_iso_buf_size
, &gEfiVirtualCdGuid
, NULL
, &DevicePath
);
1109 if (EFI_ERROR(Status
))
1111 debug("Failed to register ramdisk %r", Status
);
1115 debug("Register RamDisk %r ...", Status
);
1116 debug("RamDisk DevicePath:<%s> ...", ConvertDevicePathToText(DevicePath
, FALSE
, FALSE
));
1118 ventoy_debug_pause();
1120 gBlockData
.Path
= DevicePath
;
1121 gBlockData
.DevicePathCompareLen
= GetDevicePathSize(DevicePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
1123 Status
= ventoy_boot(ImageHandle
);
1124 if (EFI_NOT_FOUND
== Status
)
1126 gST
->ConOut
->OutputString(gST
->ConOut
, L
"No bootfile found for UEFI!\r\n");
1127 gST
->ConOut
->OutputString(gST
->ConOut
, L
"Maybe the image does not support " VENTOY_UEFI_DESC L
"!\r\n");
1134 EFI_STATUS EFIAPI VentoyEfiMain
1136 IN EFI_HANDLE ImageHandle
,
1137 IN EFI_SYSTEM_TABLE
*SystemTable
1140 EFI_STATUS Status
= EFI_SUCCESS
;
1142 g_sector_flag_num
= 512; /* initial value */
1144 g_sector_flag
= AllocatePool(g_sector_flag_num
* sizeof(ventoy_sector_flag
));
1145 if (NULL
== g_sector_flag
)
1147 return EFI_OUT_OF_RESOURCES
;
1150 gST
->ConOut
->ClearScreen(gST
->ConOut
);
1151 ventoy_clear_input();
1153 ventoy_parse_cmdline(ImageHandle
);
1157 g_ramdisk_param
.PhyAddr
= (UINT64
)(UINTN
)g_chain
;
1158 g_ramdisk_param
.DiskSize
= (UINT64
)g_iso_buf_size
;
1160 ventoy_save_ramdisk_param();
1162 ventoy_install_blockio(ImageHandle
, g_iso_buf_size
);
1163 Status
= ventoy_boot(ImageHandle
);
1164 if (EFI_NOT_FOUND
== Status
)
1166 gST
->ConOut
->OutputString(gST
->ConOut
, L
"No bootfile found for UEFI!\r\n");
1167 gST
->ConOut
->OutputString(gST
->ConOut
, L
"Maybe the image does not support " VENTOY_UEFI_DESC L
"!\r\n");
1171 ventoy_del_ramdisk_param();
1175 ventoy_set_variable();
1176 ventoy_find_iso_disk(ImageHandle
);
1180 ventoy_find_iso_disk_fs(ImageHandle
);
1181 ventoy_load_isoefi_driver(ImageHandle
);
1184 ventoy_debug_pause();
1186 ventoy_install_blockio(ImageHandle
, g_chain
->virt_img_size_in_bytes
);
1188 ventoy_debug_pause();
1190 Status
= ventoy_boot(ImageHandle
);
1191 if (EFI_NOT_FOUND
== Status
)
1193 gST
->ConOut
->OutputString(gST
->ConOut
, L
"No bootfile found for UEFI!\r\n");
1194 gST
->ConOut
->OutputString(gST
->ConOut
, L
"Maybe the image does not support " VENTOY_UEFI_DESC L
"!\r\n");
1201 ventoy_clear_input();
1202 gST
->ConOut
->ClearScreen(gST
->ConOut
);