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 UINT8
*g_iso_data_buf
= NULL
;
40 UINTN g_iso_buf_size
= 0;
41 BOOLEAN gMemdiskMode
= FALSE
;
42 BOOLEAN gSector512Mode
= FALSE
;
44 ventoy_sector_flag
*g_sector_flag
= NULL
;
45 UINT32 g_sector_flag_num
= 0;
47 EFI_FILE_OPEN g_original_fopen
= NULL
;
48 EFI_FILE_CLOSE g_original_fclose
= NULL
;
49 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME g_original_open_volume
= NULL
;
51 /* EFI block device vendor device path GUID */
52 EFI_GUID gVtoyBlockDevicePathGuid
= VTOY_BLOCK_DEVICE_PATH_GUID
;
54 #define VENTOY_ISO9660_SECTOR_OVERFLOW 2097152
56 BOOLEAN g_fixup_iso9660_secover_enable
= FALSE
;
57 BOOLEAN g_fixup_iso9660_secover_start
= FALSE
;
58 UINT64 g_fixup_iso9660_secover_1st_secs
= 0;
59 UINT64 g_fixup_iso9660_secover_cur_secs
= 0;
60 UINT64 g_fixup_iso9660_secover_tot_secs
= 0;
62 STATIC UINTN g_keyboard_hook_count
= 0;
63 STATIC BOOLEAN g_blockio_start_record_bcd
= FALSE
;
64 STATIC BOOLEAN g_blockio_bcd_read_done
= FALSE
;
66 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*g_con_simple_input_ex
= NULL
;
67 STATIC EFI_INPUT_READ_KEY_EX g_org_read_key_ex
= NULL
;
68 STATIC EFI_INPUT_READ_KEY g_org_read_key
= NULL
;
70 STATIC EFI_LOCATE_HANDLE g_org_locate_handle
= NULL
;
72 STATIC UINT8 g_sector_buf
[2048];
73 STATIC EFI_BLOCK_READ g_sector_2048_read
= NULL
;
74 STATIC EFI_BLOCK_WRITE g_sector_2048_write
= NULL
;
76 BOOLEAN
ventoy_is_cdrom_dp_exist(VOID
)
80 EFI_HANDLE
*Handles
= NULL
;
81 EFI_STATUS Status
= EFI_SUCCESS
;
82 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
= NULL
;
84 Status
= gBS
->LocateHandleBuffer(ByProtocol
, &gEfiDevicePathProtocolGuid
,
85 NULL
, &Count
, &Handles
);
86 if (EFI_ERROR(Status
))
91 for (i
= 0; i
< Count
; i
++)
93 Status
= gBS
->HandleProtocol(Handles
[i
], &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePath
);
94 if (EFI_ERROR(Status
))
99 while (!IsDevicePathEnd(DevicePath
))
101 if (MEDIA_DEVICE_PATH
== DevicePath
->Type
&& MEDIA_CDROM_DP
== DevicePath
->SubType
)
107 DevicePath
= NextDevicePathNode(DevicePath
);
116 /* Block IO procotol */
119 EFI_STATUS EFIAPI ventoy_block_io_reset
121 IN EFI_BLOCK_IO_PROTOCOL
*This
,
122 IN BOOLEAN ExtendedVerification
126 (VOID
)ExtendedVerification
;
130 STATIC EFI_STATUS EFIAPI ventoy_read_iso_sector
137 EFI_STATUS Status
= EFI_SUCCESS
;
142 UINT64 ReadStart
= 0;
144 UINT64 OverrideStart
= 0;
145 UINT64 OverrideEnd
= 0;
146 UINT8
*pCurBuf
= (UINT8
*)Buffer
;
147 ventoy_img_chunk
*pchunk
= g_chunk
;
148 ventoy_override_chunk
*pOverride
= g_override_chunk
;
149 EFI_BLOCK_IO_PROTOCOL
*pRawBlockIo
= gBlockData
.pRawBlockIo
;
151 debug("read iso sector %lu count %u", Sector
, Count
);
153 ReadStart
= Sector
* 2048;
154 ReadEnd
= (Sector
+ Count
) * 2048;
156 for (i
= 0; Count
> 0 && i
< g_img_chunk_num
; i
++, pchunk
++)
158 if (Sector
>= pchunk
->img_start_sector
&& Sector
<= pchunk
->img_end_sector
)
160 if (g_chain
->disk_sector_size
== 512)
162 MapLba
= (Sector
- pchunk
->img_start_sector
) * 4 + pchunk
->disk_start_sector
;
164 else if (g_chain
->disk_sector_size
== 1024)
166 MapLba
= (Sector
- pchunk
->img_start_sector
) * 2 + pchunk
->disk_start_sector
;
168 else if (g_chain
->disk_sector_size
== 2048)
170 MapLba
= (Sector
- pchunk
->img_start_sector
) + pchunk
->disk_start_sector
;
172 else if (g_chain
->disk_sector_size
== 4096)
174 MapLba
= ((Sector
- pchunk
->img_start_sector
) >> 1) + pchunk
->disk_start_sector
;
178 secLeft
= pchunk
->img_end_sector
+ 1 - Sector
;
179 secRead
= (Count
< secLeft
) ? Count
: secLeft
;
181 Status
= pRawBlockIo
->ReadBlocks(pRawBlockIo
, pRawBlockIo
->Media
->MediaId
,
182 MapLba
, secRead
* 2048, pCurBuf
);
183 if (EFI_ERROR(Status
))
185 debug("Raw disk read block failed %r LBA:%lu Count:%u", Status
, MapLba
, secRead
);
191 pCurBuf
+= secRead
* 2048;
195 if (ReadStart
> g_chain
->real_img_size_in_bytes
)
201 pCurBuf
= (UINT8
*)Buffer
;
202 for (i
= 0; i
< g_override_chunk_num
; i
++, pOverride
++)
204 OverrideStart
= pOverride
->img_offset
;
205 OverrideEnd
= pOverride
->img_offset
+ pOverride
->override_size
;
207 if (OverrideStart
>= ReadEnd
|| ReadStart
>= OverrideEnd
)
212 if (ReadStart
<= OverrideStart
)
214 if (ReadEnd
<= OverrideEnd
)
216 CopyMem(pCurBuf
+ OverrideStart
- ReadStart
, pOverride
->override_data
, ReadEnd
- OverrideStart
);
220 CopyMem(pCurBuf
+ OverrideStart
- ReadStart
, pOverride
->override_data
, pOverride
->override_size
);
225 if (ReadEnd
<= OverrideEnd
)
227 CopyMem(pCurBuf
, pOverride
->override_data
+ ReadStart
- OverrideStart
, ReadEnd
- ReadStart
);
231 CopyMem(pCurBuf
, pOverride
->override_data
+ ReadStart
- OverrideStart
, OverrideEnd
- ReadStart
);
235 if (g_fixup_iso9660_secover_enable
&& (!g_fixup_iso9660_secover_start
) &&
236 pOverride
->override_size
== sizeof(ventoy_iso9660_override
))
238 ventoy_iso9660_override
*dirent
= (ventoy_iso9660_override
*)pOverride
->override_data
;
239 if (dirent
->first_sector
>= VENTOY_ISO9660_SECTOR_OVERFLOW
)
241 g_fixup_iso9660_secover_start
= TRUE
;
242 g_fixup_iso9660_secover_cur_secs
= 0;
247 if (g_blockio_start_record_bcd
&& FALSE
== g_blockio_bcd_read_done
)
249 if (*(UINT32
*)Buffer
== 0x66676572)
251 g_blockio_bcd_read_done
= TRUE
;
258 STATIC EFI_STATUS EFIAPI ventoy_write_iso_sector
265 EFI_STATUS Status
= EFI_SUCCESS
;
270 UINT64 ReadStart
= 0;
272 UINT8
*pCurBuf
= (UINT8
*)Buffer
;
273 ventoy_img_chunk
*pchunk
= g_chunk
;
274 EFI_BLOCK_IO_PROTOCOL
*pRawBlockIo
= gBlockData
.pRawBlockIo
;
276 debug("write iso sector %lu count %u", Sector
, Count
);
278 ReadStart
= Sector
* 2048;
279 ReadEnd
= (Sector
+ Count
) * 2048;
281 for (i
= 0; Count
> 0 && i
< g_img_chunk_num
; i
++, pchunk
++)
283 if (Sector
>= pchunk
->img_start_sector
&& Sector
<= pchunk
->img_end_sector
)
285 if (g_chain
->disk_sector_size
== 512)
287 MapLba
= (Sector
- pchunk
->img_start_sector
) * 4 + pchunk
->disk_start_sector
;
289 else if (g_chain
->disk_sector_size
== 1024)
291 MapLba
= (Sector
- pchunk
->img_start_sector
) * 2 + pchunk
->disk_start_sector
;
293 else if (g_chain
->disk_sector_size
== 2048)
295 MapLba
= (Sector
- pchunk
->img_start_sector
) + pchunk
->disk_start_sector
;
297 else if (g_chain
->disk_sector_size
== 4096)
299 MapLba
= ((Sector
- pchunk
->img_start_sector
) >> 1) + pchunk
->disk_start_sector
;
303 secLeft
= pchunk
->img_end_sector
+ 1 - Sector
;
304 secRead
= (Count
< secLeft
) ? Count
: secLeft
;
306 Status
= pRawBlockIo
->WriteBlocks(pRawBlockIo
, pRawBlockIo
->Media
->MediaId
,
307 MapLba
, secRead
* 2048, pCurBuf
);
308 if (EFI_ERROR(Status
))
310 debug("Raw disk write block failed %r LBA:%lu Count:%u", Status
, MapLba
, secRead
);
316 pCurBuf
+= secRead
* 2048;
323 EFI_STATUS EFIAPI ventoy_block_io_ramdisk_write
325 IN EFI_BLOCK_IO_PROTOCOL
*This
,
340 return EFI_WRITE_PROTECTED
;
343 CopyMem(g_iso_data_buf
+ (Lba
* 2048), Buffer
, BufferSize
);
348 EFI_STATUS EFIAPI ventoy_block_io_ramdisk_read
350 IN EFI_BLOCK_IO_PROTOCOL
*This
,
357 //debug("### ventoy_block_io_ramdisk_read sector:%u count:%u", (UINT32)Lba, (UINT32)BufferSize / 2048);
362 CopyMem(Buffer
, g_iso_data_buf
+ (Lba
* 2048), BufferSize
);
364 if (g_blockio_start_record_bcd
&& FALSE
== g_blockio_bcd_read_done
)
366 if (*(UINT32
*)Buffer
== 0x66676572)
368 g_blockio_bcd_read_done
= TRUE
;
375 EFI_LBA EFIAPI
ventoy_fixup_iso9660_sector(IN EFI_LBA Lba
, UINT32 secNum
)
379 if (g_fixup_iso9660_secover_cur_secs
> 0)
381 Lba
+= VENTOY_ISO9660_SECTOR_OVERFLOW
;
382 g_fixup_iso9660_secover_cur_secs
+= secNum
;
383 if (g_fixup_iso9660_secover_cur_secs
>= g_fixup_iso9660_secover_tot_secs
)
385 g_fixup_iso9660_secover_start
= FALSE
;
391 ventoy_iso9660_override
*dirent
;
392 ventoy_override_chunk
*pOverride
;
394 for (i
= 0, pOverride
= g_override_chunk
; i
< g_override_chunk_num
; i
++, pOverride
++)
396 dirent
= (ventoy_iso9660_override
*)pOverride
->override_data
;
397 if (Lba
== dirent
->first_sector
)
399 g_fixup_iso9660_secover_start
= FALSE
;
404 if (g_fixup_iso9660_secover_start
)
406 for (i
= 0, pOverride
= g_override_chunk
; i
< g_override_chunk_num
; i
++, pOverride
++)
408 dirent
= (ventoy_iso9660_override
*)pOverride
->override_data
;
409 if (Lba
+ VENTOY_ISO9660_SECTOR_OVERFLOW
== dirent
->first_sector
)
411 g_fixup_iso9660_secover_tot_secs
= (dirent
->size
+ 2047) / 2048;
412 g_fixup_iso9660_secover_cur_secs
= secNum
;
413 if (g_fixup_iso9660_secover_cur_secs
>= g_fixup_iso9660_secover_tot_secs
)
415 g_fixup_iso9660_secover_start
= FALSE
;
417 Lba
+= VENTOY_ISO9660_SECTOR_OVERFLOW
;
428 EFI_STATUS EFIAPI ventoy_block_io_read
430 IN EFI_BLOCK_IO_PROTOCOL
*This
,
445 ventoy_sector_flag
*cur_flag
;
446 ventoy_virt_chunk
*node
;
448 //debug("### ventoy_block_io_read sector:%u count:%u", (UINT32)Lba, (UINT32)BufferSize / 2048);
450 secNum
= BufferSize
/ 2048;
452 /* Workaround for SSTR PE loader error */
453 if (g_fixup_iso9660_secover_start
)
455 Lba
= ventoy_fixup_iso9660_sector(Lba
, secNum
);
460 if (offset
+ BufferSize
<= g_chain
->real_img_size_in_bytes
)
462 return ventoy_read_iso_sector(Lba
, secNum
, Buffer
);
465 if (secNum
> g_sector_flag_num
)
467 cur_flag
= AllocatePool(secNum
* sizeof(ventoy_sector_flag
));
468 if (NULL
== cur_flag
)
470 return EFI_OUT_OF_RESOURCES
;
473 FreePool(g_sector_flag
);
474 g_sector_flag
= cur_flag
;
475 g_sector_flag_num
= secNum
;
478 for (curlba
= Lba
, cur_flag
= g_sector_flag
, j
= 0; j
< secNum
; j
++, curlba
++, cur_flag
++)
481 for (node
= g_virt_chunk
, i
= 0; i
< g_virt_chunk_num
; i
++, node
++)
483 if (curlba
>= node
->mem_sector_start
&& curlba
< node
->mem_sector_end
)
485 CopyMem((UINT8
*)Buffer
+ j
* 2048,
486 (char *)g_virt_chunk
+ node
->mem_sector_offset
+ (curlba
- node
->mem_sector_start
) * 2048,
491 else if (curlba
>= node
->remap_sector_start
&& curlba
< node
->remap_sector_end
)
493 cur_flag
->remap_lba
= node
->org_sector_start
+ curlba
- node
->remap_sector_start
;
500 for (curlba
= Lba
, cur_flag
= g_sector_flag
, j
= 0; j
< secNum
; j
++, curlba
++, cur_flag
++)
502 if (cur_flag
->flag
== 2)
506 lastbuffer
= (UINT8
*)Buffer
+ j
* 2048;
507 lastlba
= cur_flag
->remap_lba
;
510 else if (lastlba
+ lbacount
== cur_flag
->remap_lba
)
516 ventoy_read_iso_sector(lastlba
, lbacount
, lastbuffer
);
517 lastbuffer
= (UINT8
*)Buffer
+ j
* 2048;
518 lastlba
= cur_flag
->remap_lba
;
526 ventoy_read_iso_sector(lastlba
, lbacount
, lastbuffer
);
532 EFI_STATUS EFIAPI ventoy_block_io_write
534 IN EFI_BLOCK_IO_PROTOCOL
*This
,
549 return EFI_WRITE_PROTECTED
;
552 secNum
= BufferSize
/ 2048;
555 return ventoy_write_iso_sector(Lba
, secNum
, Buffer
);
558 EFI_STATUS EFIAPI
ventoy_block_io_flush(IN EFI_BLOCK_IO_PROTOCOL
*This
)
565 EFI_STATUS EFIAPI
ventoy_fill_device_path(VOID
)
568 UINT8 TmpBuf
[128] = {0};
569 VENDOR_DEVICE_PATH
*venPath
= NULL
;
571 venPath
= (VENDOR_DEVICE_PATH
*)TmpBuf
;
572 NameLen
= StrSize(VTOY_BLOCK_DEVICE_PATH_NAME
);
573 venPath
->Header
.Type
= HARDWARE_DEVICE_PATH
;
574 venPath
->Header
.SubType
= HW_VENDOR_DP
;
575 venPath
->Header
.Length
[0] = sizeof(VENDOR_DEVICE_PATH
) + NameLen
;
576 venPath
->Header
.Length
[1] = 0;
577 CopyMem(&venPath
->Guid
, &gVtoyBlockDevicePathGuid
, sizeof(EFI_GUID
));
578 CopyMem(venPath
+ 1, VTOY_BLOCK_DEVICE_PATH_NAME
, NameLen
);
580 gBlockData
.Path
= AppendDevicePathNode(NULL
, (EFI_DEVICE_PATH_PROTOCOL
*)TmpBuf
);
581 gBlockData
.DevicePathCompareLen
= sizeof(VENDOR_DEVICE_PATH
) + NameLen
;
583 debug("gBlockData.Path=<%s>\n", ConvertDevicePathToText(gBlockData
.Path
, FALSE
, FALSE
));
588 EFI_STATUS EFIAPI
ventoy_connect_driver(IN EFI_HANDLE ControllerHandle
, IN CONST CHAR16
*DrvName
)
592 CHAR16
*DriverName
= NULL
;
593 EFI_HANDLE
*Handles
= NULL
;
594 EFI_HANDLE DrvHandles
[2] = { NULL
};
595 EFI_STATUS Status
= EFI_SUCCESS
;
596 EFI_COMPONENT_NAME_PROTOCOL
*NameProtocol
= NULL
;
597 EFI_COMPONENT_NAME2_PROTOCOL
*Name2Protocol
= NULL
;
599 debug("ventoy_connect_driver <%s>...", DrvName
);
601 Status
= gBS
->LocateHandleBuffer(ByProtocol
, &gEfiComponentName2ProtocolGuid
,
602 NULL
, &Count
, &Handles
);
603 if (EFI_ERROR(Status
))
608 for (i
= 0; i
< Count
; i
++)
610 Status
= gBS
->HandleProtocol(Handles
[i
], &gEfiComponentName2ProtocolGuid
, (VOID
**)&Name2Protocol
);
611 if (EFI_ERROR(Status
))
616 Status
= Name2Protocol
->GetDriverName(Name2Protocol
, "en", &DriverName
);
617 if (EFI_ERROR(Status
) || NULL
== DriverName
)
622 if (StrStr(DriverName
, DrvName
))
624 debug("Find driver name2:<%s>: <%s>", DriverName
, DrvName
);
625 DrvHandles
[0] = Handles
[i
];
632 Status
= gBS
->ConnectController(ControllerHandle
, DrvHandles
, NULL
, TRUE
);
633 debug("ventoy_connect_driver:<%s> <%r>", DrvName
, Status
);
637 debug("%s NOT found, now try COMPONENT_NAME", DrvName
);
643 Status
= gBS
->LocateHandleBuffer(ByProtocol
, &gEfiComponentNameProtocolGuid
,
644 NULL
, &Count
, &Handles
);
645 if (EFI_ERROR(Status
))
650 for (i
= 0; i
< Count
; i
++)
652 Status
= gBS
->HandleProtocol(Handles
[i
], &gEfiComponentNameProtocolGuid
, (VOID
**)&NameProtocol
);
653 if (EFI_ERROR(Status
))
658 Status
= NameProtocol
->GetDriverName(NameProtocol
, "en", &DriverName
);
659 if (EFI_ERROR(Status
))
664 if (StrStr(DriverName
, DrvName
))
666 debug("Find driver name:<%s>: <%s>", DriverName
, DrvName
);
667 DrvHandles
[0] = Handles
[i
];
674 Status
= gBS
->ConnectController(ControllerHandle
, DrvHandles
, NULL
, TRUE
);
675 debug("ventoy_connect_driver:<%s> <%r>", DrvName
, Status
);
679 Status
= EFI_NOT_FOUND
;
687 EFI_STATUS EFIAPI ventoy_block_io_read_512
689 IN EFI_BLOCK_IO_PROTOCOL
*This
,
698 UINT8
*CurBuf
= NULL
;
699 EFI_STATUS Status
= EFI_SUCCESS
;
701 debug("ventoy_block_io_read_512 %lu %lu\n", Lba
, BufferSize
/ 512);
703 CurBuf
= (UINT8
*)Buffer
;
708 Status
|= g_sector_2048_read(This
, MediaId
, Lba
/ 4, 2048, g_sector_buf
);
710 if (BufferSize
<= (4 - Mod
) * 512)
712 CopyMem(CurBuf
, g_sector_buf
+ Mod
* 512, BufferSize
);
717 ReadSize
= (4 - Mod
) * 512;
718 CopyMem(CurBuf
, g_sector_buf
+ Mod
* 512, ReadSize
);
721 BufferSize
-= ReadSize
;
725 if (BufferSize
>= 2048)
727 ReadSize
= BufferSize
/ 2048 * 2048;
729 Status
|= g_sector_2048_read(This
, MediaId
, Lba
/ 4, ReadSize
, CurBuf
);
732 Lba
+= ReadSize
/ 512;
733 BufferSize
-= ReadSize
;
738 Status
|= g_sector_2048_read(This
, MediaId
, Lba
/ 4, 2048, g_sector_buf
);
739 CopyMem(CurBuf
, g_sector_buf
, BufferSize
);
745 EFI_STATUS EFIAPI ventoy_block_io_write_512
747 IN EFI_BLOCK_IO_PROTOCOL
*This
,
756 UINT8
*CurBuf
= NULL
;
757 EFI_STATUS Status
= EFI_SUCCESS
;
759 debug("ventoy_block_io_write_512 %lu %lu\n", Lba
, BufferSize
/ 512);
761 CurBuf
= (UINT8
*)Buffer
;
766 Status
|= g_sector_2048_read(This
, MediaId
, Lba
/ 4, 2048, g_sector_buf
);
768 if (BufferSize
<= (4 - Mod
) * 512)
770 CopyMem(g_sector_buf
+ Mod
* 512, CurBuf
, BufferSize
);
771 return g_sector_2048_write(This
, MediaId
, Lba
/ 4, 2048, g_sector_buf
);
775 ReadSize
= (4 - Mod
) * 512;
776 CopyMem(g_sector_buf
+ Mod
* 512, CurBuf
, ReadSize
);
777 g_sector_2048_write(This
, MediaId
, Lba
/ 4, 2048, g_sector_buf
);
781 BufferSize
-= ReadSize
;
785 if (BufferSize
>= 2048)
787 ReadSize
= BufferSize
/ 2048 * 2048;
789 Status
|= g_sector_2048_write(This
, MediaId
, Lba
/ 4, ReadSize
, CurBuf
);
792 Lba
+= ReadSize
/ 512;
793 BufferSize
-= ReadSize
;
798 Status
|= g_sector_2048_read(This
, MediaId
, Lba
/ 4, 2048, g_sector_buf
);
800 CopyMem(g_sector_buf
, CurBuf
, BufferSize
);
801 g_sector_2048_write(This
, MediaId
, Lba
/ 4, 2048, g_sector_buf
);
807 EFI_STATUS EFIAPI
ventoy_install_blockio(IN EFI_HANDLE ImageHandle
, IN UINT64 ImgSize
)
809 EFI_STATUS Status
= EFI_SUCCESS
;
810 EFI_BLOCK_IO_PROTOCOL
*pBlockIo
= &(gBlockData
.BlockIo
);
812 ventoy_fill_device_path();
814 debug("install block io protocol %p", ImageHandle
);
815 ventoy_debug_pause();
819 gBlockData
.Media
.BlockSize
= 512;
820 gBlockData
.Media
.LastBlock
= ImgSize
/ 512 - 1;
824 gBlockData
.Media
.BlockSize
= 2048;
825 gBlockData
.Media
.LastBlock
= ImgSize
/ 2048 - 1;
828 gBlockData
.Media
.ReadOnly
= TRUE
;
829 gBlockData
.Media
.MediaPresent
= 1;
830 gBlockData
.Media
.LogicalBlocksPerPhysicalBlock
= 1;
832 pBlockIo
->Revision
= EFI_BLOCK_IO_PROTOCOL_REVISION3
;
833 pBlockIo
->Media
= &(gBlockData
.Media
);
834 pBlockIo
->Reset
= ventoy_block_io_reset
;
838 g_sector_2048_read
= gMemdiskMode
? ventoy_block_io_ramdisk_read
: ventoy_block_io_read
;
839 g_sector_2048_write
= gMemdiskMode
? ventoy_block_io_ramdisk_write
: ventoy_block_io_write
;
840 pBlockIo
->ReadBlocks
= ventoy_block_io_read_512
;
841 pBlockIo
->WriteBlocks
= ventoy_block_io_write_512
;
845 pBlockIo
->ReadBlocks
= gMemdiskMode
? ventoy_block_io_ramdisk_read
: ventoy_block_io_read
;
846 pBlockIo
->WriteBlocks
= ventoy_block_io_write
;
849 pBlockIo
->FlushBlocks
= ventoy_block_io_flush
;
851 Status
= gBS
->InstallMultipleProtocolInterfaces(&gBlockData
.Handle
,
852 &gEfiBlockIoProtocolGuid
, &gBlockData
.BlockIo
,
853 &gEfiDevicePathProtocolGuid
, gBlockData
.Path
,
855 debug("Install protocol %r %p", Status
, gBlockData
.Handle
);
856 if (EFI_ERROR(Status
))
861 Status
= ventoy_connect_driver(gBlockData
.Handle
, L
"Disk I/O Driver");
862 debug("Connect disk IO driver %r", Status
);
864 Status
= ventoy_connect_driver(gBlockData
.Handle
, L
"Partition Driver");
865 debug("Connect partition driver %r", Status
);
866 if (EFI_ERROR(Status
))
868 Status
= gBS
->ConnectController(gBlockData
.Handle
, NULL
, NULL
, TRUE
);
869 debug("Connect all controller %r", Status
);
872 ventoy_debug_pause();
878 /* For file replace */
881 STATIC EFI_STATUS EFIAPI
882 ventoy_wrapper_fs_open(EFI_FILE_HANDLE This
, EFI_FILE_HANDLE
*New
, CHAR16
*Name
, UINT64 Mode
, UINT64 Attributes
)
892 STATIC EFI_STATUS EFIAPI
893 ventoy_wrapper_file_open_ex(EFI_FILE_HANDLE This
, EFI_FILE_HANDLE
*New
, CHAR16
*Name
, UINT64 Mode
, UINT64 Attributes
, EFI_FILE_IO_TOKEN
*Token
)
895 return ventoy_wrapper_fs_open(This
, New
, Name
, Mode
, Attributes
);
898 STATIC EFI_STATUS EFIAPI
899 ventoy_wrapper_file_delete(EFI_FILE_HANDLE This
)
905 STATIC EFI_STATUS EFIAPI
906 ventoy_wrapper_file_set_info(EFI_FILE_HANDLE This
, EFI_GUID
*Type
, UINTN Len
, VOID
*Data
)
911 STATIC EFI_STATUS EFIAPI
912 ventoy_wrapper_file_flush(EFI_FILE_HANDLE This
)
919 STATIC EFI_STATUS EFIAPI
920 ventoy_wrapper_file_flush_ex(EFI_FILE_HANDLE This
, EFI_FILE_IO_TOKEN
*Token
)
928 STATIC EFI_STATUS EFIAPI
929 ventoy_wrapper_file_write(EFI_FILE_HANDLE This
, UINTN
*Len
, VOID
*Data
)
935 return EFI_WRITE_PROTECTED
;
938 STATIC EFI_STATUS EFIAPI
939 ventoy_wrapper_file_write_ex(IN EFI_FILE_PROTOCOL
*This
, IN OUT EFI_FILE_IO_TOKEN
*Token
)
941 return ventoy_wrapper_file_write(This
, &(Token
->BufferSize
), Token
->Buffer
);
945 STATIC EFI_STATUS EFIAPI
946 ventoy_wrapper_file_close(EFI_FILE_HANDLE This
)
953 STATIC EFI_STATUS EFIAPI
954 ventoy_wrapper_file_set_pos(EFI_FILE_HANDLE This
, UINT64 Position
)
958 if (Position
<= g_efi_file_replace
.FileSizeBytes
)
960 g_efi_file_replace
.CurPos
= Position
;
964 g_efi_file_replace
.CurPos
= g_efi_file_replace
.FileSizeBytes
;
970 STATIC EFI_STATUS EFIAPI
971 ventoy_wrapper_file_get_pos(EFI_FILE_HANDLE This
, UINT64
*Position
)
975 *Position
= g_efi_file_replace
.CurPos
;
981 STATIC EFI_STATUS EFIAPI
982 ventoy_wrapper_file_get_info(EFI_FILE_HANDLE This
, EFI_GUID
*Type
, UINTN
*Len
, VOID
*Data
)
984 EFI_FILE_INFO
*Info
= (EFI_FILE_INFO
*) Data
;
986 debug("ventoy_wrapper_file_get_info ... %u", *Len
);
988 if (!CompareGuid(Type
, &gEfiFileInfoGuid
))
990 return EFI_INVALID_PARAMETER
;
996 return EFI_BUFFER_TOO_SMALL
;
999 ZeroMem(Data
, sizeof(EFI_FILE_INFO
));
1001 Info
->Size
= sizeof(EFI_FILE_INFO
);
1002 Info
->FileSize
= g_efi_file_replace
.FileSizeBytes
;
1003 Info
->PhysicalSize
= g_efi_file_replace
.FileSizeBytes
;
1004 Info
->Attribute
= EFI_FILE_READ_ONLY
;
1005 //Info->FileName = EFI_FILE_READ_ONLY;
1012 STATIC EFI_STATUS EFIAPI
1013 ventoy_wrapper_file_read(EFI_FILE_HANDLE This
, UINTN
*Len
, VOID
*Data
)
1016 UINTN ReadLen
= *Len
;
1020 debug("ventoy_wrapper_file_read ... %u", *Len
);
1022 if (g_efi_file_replace
.CurPos
+ ReadLen
> g_efi_file_replace
.FileSizeBytes
)
1024 ReadLen
= g_efi_file_replace
.FileSizeBytes
- g_efi_file_replace
.CurPos
;
1027 Lba
= g_efi_file_replace
.CurPos
/ 2048 + g_efi_file_replace
.BlockIoSectorStart
;
1029 ventoy_block_io_read(NULL
, 0, Lba
, ReadLen
, Data
);
1033 g_efi_file_replace
.CurPos
+= ReadLen
;
1038 STATIC EFI_STATUS EFIAPI
1039 ventoy_wrapper_file_read_ex(IN EFI_FILE_PROTOCOL
*This
, IN OUT EFI_FILE_IO_TOKEN
*Token
)
1041 return ventoy_wrapper_file_read(This
, &(Token
->BufferSize
), Token
->Buffer
);
1044 STATIC EFI_STATUS EFIAPI
ventoy_wrapper_file_procotol(EFI_FILE_PROTOCOL
*File
)
1046 File
->Revision
= EFI_FILE_PROTOCOL_REVISION2
;
1047 File
->Open
= ventoy_wrapper_fs_open
;
1048 File
->Close
= ventoy_wrapper_file_close
;
1049 File
->Delete
= ventoy_wrapper_file_delete
;
1050 File
->Read
= ventoy_wrapper_file_read
;
1051 File
->Write
= ventoy_wrapper_file_write
;
1052 File
->GetPosition
= ventoy_wrapper_file_get_pos
;
1053 File
->SetPosition
= ventoy_wrapper_file_set_pos
;
1054 File
->GetInfo
= ventoy_wrapper_file_get_info
;
1055 File
->SetInfo
= ventoy_wrapper_file_set_info
;
1056 File
->Flush
= ventoy_wrapper_file_flush
;
1057 File
->OpenEx
= ventoy_wrapper_file_open_ex
;
1058 File
->ReadEx
= ventoy_wrapper_file_read_ex
;
1059 File
->WriteEx
= ventoy_wrapper_file_write_ex
;
1060 File
->FlushEx
= ventoy_wrapper_file_flush_ex
;
1065 STATIC EFI_STATUS EFIAPI ventoy_wrapper_file_open
1067 EFI_FILE_HANDLE This
,
1068 EFI_FILE_HANDLE
*New
,
1077 EFI_STATUS Status
= EFI_SUCCESS
;
1079 ventoy_virt_chunk
*virt
= NULL
;
1081 debug("## ventoy_wrapper_file_open <%s> ", Name
);
1083 Status
= g_original_fopen(This
, New
, Name
, Mode
, Attributes
);
1084 if (EFI_ERROR(Status
))
1089 if (g_file_replace_list
&& g_file_replace_list
->magic
== GRUB_FILE_REPLACE_MAGIC
&&
1090 g_file_replace_list
->new_file_virtual_id
< g_virt_chunk_num
)
1092 AsciiSPrint(TmpName
, sizeof(TmpName
), "%s", Name
);
1093 for (j
= 0; j
< 4; j
++)
1095 if (0 == AsciiStrCmp(g_file_replace_list
[i
].old_file_name
[j
], TmpName
))
1097 g_original_fclose(*New
);
1098 *New
= &g_efi_file_replace
.WrapperHandle
;
1099 ventoy_wrapper_file_procotol(*New
);
1101 virt
= g_virt_chunk
+ g_file_replace_list
->new_file_virtual_id
;
1103 Sectors
= (virt
->mem_sector_end
- virt
->mem_sector_start
) + (virt
->remap_sector_end
- virt
->remap_sector_start
);
1105 g_efi_file_replace
.BlockIoSectorStart
= virt
->mem_sector_start
;
1106 g_efi_file_replace
.FileSizeBytes
= Sectors
* 2048;
1110 debug("## ventoy_wrapper_file_open <%s> BlockStart:%lu Sectors:%lu Bytes:%lu", Name
,
1111 g_efi_file_replace
.BlockIoSectorStart
, Sectors
, Sectors
* 2048);
1119 if (StrCmp(Name
, L
"\\EFI\\BOOT") == 0)
1121 (*New
)->Open
= ventoy_wrapper_file_open
;
1128 EFI_STATUS EFIAPI ventoy_wrapper_open_volume
1130 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*This
,
1131 OUT EFI_FILE_PROTOCOL
**Root
1134 EFI_STATUS Status
= EFI_SUCCESS
;
1136 Status
= g_original_open_volume(This
, Root
);
1137 if (!EFI_ERROR(Status
))
1139 g_original_fopen
= (*Root
)->Open
;
1140 g_original_fclose
= (*Root
)->Close
;
1141 (*Root
)->Open
= ventoy_wrapper_file_open
;
1147 EFI_STATUS EFIAPI
ventoy_wrapper_push_openvolume(IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME OpenVolume
)
1149 g_original_open_volume
= OpenVolume
;
1154 /* For auto skip Windows 'Press any key to boot from CD or DVD ...' */
1157 STATIC EFI_STATUS EFIAPI ventoy_wrapper_read_key_ex
1159 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
1160 OUT EFI_KEY_DATA
*KeyData
1163 /* only hook once before BCD file read */
1164 if (g_keyboard_hook_count
== 0 && g_blockio_bcd_read_done
== FALSE
)
1166 g_keyboard_hook_count
++;
1168 KeyData
->Key
.ScanCode
= SCAN_DELETE
;
1169 KeyData
->Key
.UnicodeChar
= 0;
1170 KeyData
->KeyState
.KeyShiftState
= 0;
1171 KeyData
->KeyState
.KeyToggleState
= 0;
1176 return g_org_read_key_ex(This
, KeyData
);
1179 EFI_STATUS EFIAPI ventoy_wrapper_read_key
1181 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
1182 OUT EFI_INPUT_KEY
*Key
1185 /* only hook once before BCD file read */
1186 if (g_keyboard_hook_count
== 0 && g_blockio_bcd_read_done
== FALSE
)
1188 g_keyboard_hook_count
++;
1190 Key
->ScanCode
= SCAN_DELETE
;
1191 Key
->UnicodeChar
= 0;
1195 return g_org_read_key(This
, Key
);
1198 EFI_STATUS
ventoy_hook_keyboard_start(VOID
)
1200 g_blockio_start_record_bcd
= TRUE
;
1201 g_blockio_bcd_read_done
= FALSE
;
1202 g_keyboard_hook_count
= 0;
1204 if (g_con_simple_input_ex
)
1206 g_org_read_key_ex
= g_con_simple_input_ex
->ReadKeyStrokeEx
;
1207 g_con_simple_input_ex
->ReadKeyStrokeEx
= ventoy_wrapper_read_key_ex
;
1210 g_org_read_key
= gST
->ConIn
->ReadKeyStroke
;
1211 gST
->ConIn
->ReadKeyStroke
= ventoy_wrapper_read_key
;
1216 EFI_STATUS
ventoy_hook_keyboard_stop(VOID
)
1218 g_blockio_start_record_bcd
= FALSE
;
1219 g_blockio_bcd_read_done
= FALSE
;
1220 g_keyboard_hook_count
= 0;
1222 if (g_con_simple_input_ex
)
1224 g_con_simple_input_ex
->ReadKeyStrokeEx
= g_org_read_key_ex
;
1227 gST
->ConIn
->ReadKeyStroke
= g_org_read_key
;
1233 /* Fixup the 1st cdrom influnce for Windows boot */
1236 STATIC EFI_STATUS EFIAPI ventoy_wrapper_locate_handle
1238 IN EFI_LOCATE_SEARCH_TYPE SearchType
,
1239 IN EFI_GUID
*Protocol
, OPTIONAL
1240 IN VOID
*SearchKey
, OPTIONAL
1241 IN OUT UINTN
*BufferSize
,
1242 OUT EFI_HANDLE
*Buffer
1246 EFI_HANDLE Handle
= NULL
;
1247 EFI_STATUS Status
= EFI_SUCCESS
;
1249 Status
= g_org_locate_handle(SearchType
, Protocol
, SearchKey
, BufferSize
, Buffer
);
1251 if (EFI_SUCCESS
== Status
&& Protocol
&& CompareGuid(&gEfiBlockIoProtocolGuid
, Protocol
))
1253 for (i
= 0; i
< (*BufferSize
) / sizeof(EFI_HANDLE
); i
++)
1255 if (Buffer
[i
] == gBlockData
.Handle
)
1258 Buffer
[0] = Buffer
[i
];
1268 EFI_STATUS
ventoy_hook_1st_cdrom_start(VOID
)
1270 g_org_locate_handle
= gBS
->LocateHandle
;
1271 gBS
->LocateHandle
= ventoy_wrapper_locate_handle
;
1276 EFI_STATUS
ventoy_hook_1st_cdrom_stop(VOID
)
1278 gBS
->LocateHandle
= g_org_locate_handle
;
1279 g_org_locate_handle
= NULL
;