]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/VentoyProtocol.c
Fix the issue that install media not recognized when install Clear Linux. (#1674)
[Ventoy.git] / EDK2 / edk2_mod / edk2-edk2-stable201911 / MdeModulePkg / Application / Ventoy / VentoyProtocol.c
1 /******************************************************************************
2 * Ventoy.c
3 *
4 * Copyright (c) 2020, longpanda <admin@ventoy.net>
5 *
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.
10 *
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.
15 *
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/>.
18 *
19 */
20
21 #include <Uefi.h>
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>
37 #include <Protocol/DriverBinding.h>
38 #include <Ventoy.h>
39
40 #define ASSIGN_REPLACE(This, replace) \
41 replace = (This->FlushEx == ventoy_wrapper_file_flush_ex) ? &g_efi_file_replace : &g_img_file_replace
42
43 UINT8 *g_iso_data_buf = NULL;
44 UINTN g_iso_buf_size = 0;
45 BOOLEAN gMemdiskMode = FALSE;
46 BOOLEAN gSector512Mode = FALSE;
47
48 ventoy_sector_flag *g_sector_flag = NULL;
49 UINT32 g_sector_flag_num = 0;
50
51 EFI_FILE_OPEN g_original_fopen = NULL;
52 EFI_FILE_CLOSE g_original_fclose = NULL;
53 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME g_original_open_volume = NULL;
54
55 /* EFI block device vendor device path GUID */
56 EFI_GUID gVtoyBlockDevicePathGuid = VTOY_BLOCK_DEVICE_PATH_GUID;
57
58 #define VENTOY_ISO9660_SECTOR_OVERFLOW 2097152
59
60 BOOLEAN g_fixup_iso9660_secover_enable = FALSE;
61 BOOLEAN g_fixup_iso9660_secover_start = FALSE;
62 UINT64 g_fixup_iso9660_secover_1st_secs = 0;
63 UINT64 g_fixup_iso9660_secover_cur_secs = 0;
64 UINT64 g_fixup_iso9660_secover_tot_secs = 0;
65
66 STATIC UINTN g_keyboard_hook_count = 0;
67 STATIC BOOLEAN g_blockio_start_record_bcd = FALSE;
68 STATIC BOOLEAN g_blockio_bcd_read_done = FALSE;
69
70 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *g_con_simple_input_ex = NULL;
71 STATIC EFI_INPUT_READ_KEY_EX g_org_read_key_ex = NULL;
72 STATIC EFI_INPUT_READ_KEY g_org_read_key = NULL;
73
74 STATIC EFI_LOCATE_HANDLE g_org_locate_handle = NULL;
75
76 STATIC UINT8 g_sector_buf[2048];
77 STATIC EFI_BLOCK_READ g_sector_2048_read = NULL;
78 STATIC EFI_BLOCK_WRITE g_sector_2048_write = NULL;
79
80 STATIC UINTN g_DriverBindWrapperCnt = 0;
81 STATIC DRIVER_BIND_WRAPPER g_DriverBindWrapperList[MAX_DRIVER_BIND_WRAPPER];
82
83 BOOLEAN ventoy_is_cdrom_dp_exist(VOID)
84 {
85 UINTN i = 0;
86 UINTN Count = 0;
87 EFI_HANDLE *Handles = NULL;
88 EFI_STATUS Status = EFI_SUCCESS;
89 EFI_DEVICE_PATH_PROTOCOL *DevicePath = NULL;
90
91 Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiDevicePathProtocolGuid,
92 NULL, &Count, &Handles);
93 if (EFI_ERROR(Status))
94 {
95 return FALSE;
96 }
97
98 for (i = 0; i < Count; i++)
99 {
100 Status = gBS->HandleProtocol(Handles[i], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePath);
101 if (EFI_ERROR(Status))
102 {
103 continue;
104 }
105
106 while (!IsDevicePathEnd(DevicePath))
107 {
108 if (MEDIA_DEVICE_PATH == DevicePath->Type && MEDIA_CDROM_DP == DevicePath->SubType)
109 {
110 FreePool(Handles);
111 return TRUE;
112 }
113
114 DevicePath = NextDevicePathNode(DevicePath);
115 }
116 }
117
118 FreePool(Handles);
119 return FALSE;
120 }
121
122 #if 0
123 /* Block IO procotol */
124 #endif
125
126 EFI_STATUS EFIAPI ventoy_block_io_reset
127 (
128 IN EFI_BLOCK_IO_PROTOCOL *This,
129 IN BOOLEAN ExtendedVerification
130 )
131 {
132 (VOID)This;
133 (VOID)ExtendedVerification;
134 return EFI_SUCCESS;
135 }
136
137 STATIC EFI_STATUS EFIAPI ventoy_read_iso_sector
138 (
139 IN UINT64 Sector,
140 IN UINTN Count,
141 OUT VOID *Buffer
142 )
143 {
144 EFI_STATUS Status = EFI_SUCCESS;
145 EFI_LBA MapLba = 0;
146 UINT32 i = 0;
147 UINTN secLeft = 0;
148 UINTN secRead = 0;
149 UINT64 ReadStart = 0;
150 UINT64 ReadEnd = 0;
151 UINT64 OverrideStart = 0;
152 UINT64 OverrideEnd= 0;
153 UINT8 *pCurBuf = (UINT8 *)Buffer;
154 ventoy_img_chunk *pchunk = g_chunk;
155 ventoy_override_chunk *pOverride = g_override_chunk;
156 EFI_BLOCK_IO_PROTOCOL *pRawBlockIo = gBlockData.pRawBlockIo;
157
158 debug("read iso sector %lu count %u Buffer:%p Align:%u blk:%u",
159 Sector, Count, Buffer, pRawBlockIo->Media->IoAlign, pRawBlockIo->Media->BlockSize);
160
161 ReadStart = Sector * 2048;
162 ReadEnd = (Sector + Count) * 2048;
163
164 for (i = 0; Count > 0 && i < g_img_chunk_num; i++, pchunk++)
165 {
166 if (Sector >= pchunk->img_start_sector && Sector <= pchunk->img_end_sector)
167 {
168 if (g_chain->disk_sector_size == 512)
169 {
170 MapLba = (Sector - pchunk->img_start_sector) * 4 + pchunk->disk_start_sector;
171 }
172 else if (g_chain->disk_sector_size == 1024)
173 {
174 MapLba = (Sector - pchunk->img_start_sector) * 2 + pchunk->disk_start_sector;
175 }
176 else if (g_chain->disk_sector_size == 2048)
177 {
178 MapLba = (Sector - pchunk->img_start_sector) + pchunk->disk_start_sector;
179 }
180 else if (g_chain->disk_sector_size == 4096)
181 {
182 MapLba = ((Sector - pchunk->img_start_sector) >> 1) + pchunk->disk_start_sector;
183 }
184
185 secLeft = pchunk->img_end_sector + 1 - Sector;
186 secRead = (Count < secLeft) ? Count : secLeft;
187
188 Status = pRawBlockIo->ReadBlocks(pRawBlockIo, pRawBlockIo->Media->MediaId,
189 MapLba, secRead * 2048, pCurBuf);
190 if (EFI_ERROR(Status))
191 {
192 debug("Raw disk read block failed %r LBA:%lu Count:%u %p", Status, MapLba, secRead, pCurBuf);
193 return Status;
194 }
195
196 Count -= secRead;
197 Sector += secRead;
198 pCurBuf += secRead * 2048;
199 }
200 }
201
202 if (ReadStart > g_chain->real_img_size_in_bytes)
203 {
204 return EFI_SUCCESS;
205 }
206
207 /* override data */
208 pCurBuf = (UINT8 *)Buffer;
209 for (i = 0; i < g_override_chunk_num; i++, pOverride++)
210 {
211 OverrideStart = pOverride->img_offset;
212 OverrideEnd = pOverride->img_offset + pOverride->override_size;
213
214 if (OverrideStart >= ReadEnd || ReadStart >= OverrideEnd)
215 {
216 continue;
217 }
218
219 if (ReadStart <= OverrideStart)
220 {
221 if (ReadEnd <= OverrideEnd)
222 {
223 CopyMem(pCurBuf + OverrideStart - ReadStart, pOverride->override_data, ReadEnd - OverrideStart);
224 }
225 else
226 {
227 CopyMem(pCurBuf + OverrideStart - ReadStart, pOverride->override_data, pOverride->override_size);
228 }
229 }
230 else
231 {
232 if (ReadEnd <= OverrideEnd)
233 {
234 CopyMem(pCurBuf, pOverride->override_data + ReadStart - OverrideStart, ReadEnd - ReadStart);
235 }
236 else
237 {
238 CopyMem(pCurBuf, pOverride->override_data + ReadStart - OverrideStart, OverrideEnd - ReadStart);
239 }
240 }
241
242 if (g_fixup_iso9660_secover_enable && (!g_fixup_iso9660_secover_start) &&
243 pOverride->override_size == sizeof(ventoy_iso9660_override))
244 {
245 ventoy_iso9660_override *dirent = (ventoy_iso9660_override *)pOverride->override_data;
246 if (dirent->first_sector >= VENTOY_ISO9660_SECTOR_OVERFLOW)
247 {
248 g_fixup_iso9660_secover_start = TRUE;
249 g_fixup_iso9660_secover_cur_secs = 0;
250 }
251 }
252 }
253
254 if (g_blockio_start_record_bcd && FALSE == g_blockio_bcd_read_done)
255 {
256 if (*(UINT32 *)Buffer == 0x66676572)
257 {
258 g_blockio_bcd_read_done = TRUE;
259 }
260 }
261
262 return EFI_SUCCESS;
263 }
264
265 STATIC EFI_STATUS EFIAPI ventoy_write_iso_sector
266 (
267 IN UINT64 Sector,
268 IN UINTN Count,
269 IN VOID *Buffer
270 )
271 {
272 EFI_STATUS Status = EFI_SUCCESS;
273 EFI_LBA MapLba = 0;
274 UINT32 i = 0;
275 UINTN secLeft = 0;
276 UINTN secRead = 0;
277 UINT64 ReadStart = 0;
278 UINT64 ReadEnd = 0;
279 UINT8 *pCurBuf = (UINT8 *)Buffer;
280 ventoy_img_chunk *pchunk = g_chunk;
281 EFI_BLOCK_IO_PROTOCOL *pRawBlockIo = gBlockData.pRawBlockIo;
282
283 debug("write iso sector %lu count %u", Sector, Count);
284
285 ReadStart = Sector * 2048;
286 ReadEnd = (Sector + Count) * 2048;
287
288 for (i = 0; Count > 0 && i < g_img_chunk_num; i++, pchunk++)
289 {
290 if (Sector >= pchunk->img_start_sector && Sector <= pchunk->img_end_sector)
291 {
292 if (g_chain->disk_sector_size == 512)
293 {
294 MapLba = (Sector - pchunk->img_start_sector) * 4 + pchunk->disk_start_sector;
295 }
296 else if (g_chain->disk_sector_size == 1024)
297 {
298 MapLba = (Sector - pchunk->img_start_sector) * 2 + pchunk->disk_start_sector;
299 }
300 else if (g_chain->disk_sector_size == 2048)
301 {
302 MapLba = (Sector - pchunk->img_start_sector) + pchunk->disk_start_sector;
303 }
304 else if (g_chain->disk_sector_size == 4096)
305 {
306 MapLba = ((Sector - pchunk->img_start_sector) >> 1) + pchunk->disk_start_sector;
307 }
308
309
310 secLeft = pchunk->img_end_sector + 1 - Sector;
311 secRead = (Count < secLeft) ? Count : secLeft;
312
313 Status = pRawBlockIo->WriteBlocks(pRawBlockIo, pRawBlockIo->Media->MediaId,
314 MapLba, secRead * 2048, pCurBuf);
315 if (EFI_ERROR(Status))
316 {
317 debug("Raw disk write block failed %r LBA:%lu Count:%u", Status, MapLba, secRead);
318 return Status;
319 }
320
321 Count -= secRead;
322 Sector += secRead;
323 pCurBuf += secRead * 2048;
324 }
325 }
326
327 return EFI_SUCCESS;
328 }
329
330 EFI_STATUS EFIAPI ventoy_block_io_ramdisk_write
331 (
332 IN EFI_BLOCK_IO_PROTOCOL *This,
333 IN UINT32 MediaId,
334 IN EFI_LBA Lba,
335 IN UINTN BufferSize,
336 IN VOID *Buffer
337 )
338 {
339 (VOID)This;
340 (VOID)MediaId;
341 (VOID)Lba;
342 (VOID)BufferSize;
343 (VOID)Buffer;
344
345 if (!gSector512Mode)
346 {
347 return EFI_WRITE_PROTECTED;
348 }
349
350 CopyMem(g_iso_data_buf + (Lba * 2048), Buffer, BufferSize);
351
352 return EFI_SUCCESS;
353 }
354
355 EFI_STATUS EFIAPI ventoy_block_io_ramdisk_read
356 (
357 IN EFI_BLOCK_IO_PROTOCOL *This,
358 IN UINT32 MediaId,
359 IN EFI_LBA Lba,
360 IN UINTN BufferSize,
361 OUT VOID *Buffer
362 )
363 {
364 //debug("### ventoy_block_io_ramdisk_read sector:%u count:%u", (UINT32)Lba, (UINT32)BufferSize / 2048);
365
366 (VOID)This;
367 (VOID)MediaId;
368
369 CopyMem(Buffer, g_iso_data_buf + (Lba * 2048), BufferSize);
370
371 if (g_blockio_start_record_bcd && FALSE == g_blockio_bcd_read_done)
372 {
373 if (*(UINT32 *)Buffer == 0x66676572)
374 {
375 g_blockio_bcd_read_done = TRUE;
376 }
377 }
378
379 return EFI_SUCCESS;
380 }
381
382 EFI_LBA EFIAPI ventoy_fixup_iso9660_sector(IN EFI_LBA Lba, UINT32 secNum)
383 {
384 UINT32 i = 0;
385
386 if (g_fixup_iso9660_secover_cur_secs > 0)
387 {
388 Lba += VENTOY_ISO9660_SECTOR_OVERFLOW;
389 g_fixup_iso9660_secover_cur_secs += secNum;
390 if (g_fixup_iso9660_secover_cur_secs >= g_fixup_iso9660_secover_tot_secs)
391 {
392 g_fixup_iso9660_secover_start = FALSE;
393 goto end;
394 }
395 }
396 else
397 {
398 ventoy_iso9660_override *dirent;
399 ventoy_override_chunk *pOverride;
400
401 for (i = 0, pOverride = g_override_chunk; i < g_override_chunk_num; i++, pOverride++)
402 {
403 dirent = (ventoy_iso9660_override *)pOverride->override_data;
404 if (Lba == dirent->first_sector)
405 {
406 g_fixup_iso9660_secover_start = FALSE;
407 goto end;
408 }
409 }
410
411 if (g_fixup_iso9660_secover_start)
412 {
413 for (i = 0, pOverride = g_override_chunk; i < g_override_chunk_num; i++, pOverride++)
414 {
415 dirent = (ventoy_iso9660_override *)pOverride->override_data;
416 if (Lba + VENTOY_ISO9660_SECTOR_OVERFLOW == dirent->first_sector)
417 {
418 g_fixup_iso9660_secover_tot_secs = (dirent->size + 2047) / 2048;
419 g_fixup_iso9660_secover_cur_secs = secNum;
420 if (g_fixup_iso9660_secover_cur_secs >= g_fixup_iso9660_secover_tot_secs)
421 {
422 g_fixup_iso9660_secover_start = FALSE;
423 }
424 Lba += VENTOY_ISO9660_SECTOR_OVERFLOW;
425 goto end;
426 }
427 }
428 }
429 }
430
431 end:
432 return Lba;
433 }
434
435 EFI_STATUS EFIAPI ventoy_block_io_read_real
436 (
437 IN EFI_BLOCK_IO_PROTOCOL *This,
438 IN UINT32 MediaId,
439 IN EFI_LBA Lba,
440 IN UINTN BufferSize,
441 OUT VOID *Buffer
442 )
443 {
444 UINT32 i = 0;
445 UINT32 j = 0;
446 UINT32 lbacount = 0;
447 UINT32 secNum = 0;
448 UINT32 TmpNum = 0;
449 UINT64 VirtSec = 0;
450 UINT64 offset = 0;
451 EFI_LBA curlba = 0;
452 EFI_LBA lastlba = 0;
453 UINT8 *lastbuffer;
454 ventoy_sector_flag *cur_flag;
455 ventoy_virt_chunk *node;
456
457 debug("### block_io_read_real sector:%u count:%u Buffer:%p", (UINT32)Lba, (UINT32)BufferSize / 2048, Buffer);
458
459 secNum = BufferSize / 2048;
460
461 /* Workaround for SSTR PE loader error */
462 if (g_fixup_iso9660_secover_start)
463 {
464 Lba = ventoy_fixup_iso9660_sector(Lba, secNum);
465 }
466
467 offset = Lba * 2048;
468
469 if (offset + BufferSize <= g_chain->real_img_size_in_bytes)
470 {
471 return ventoy_read_iso_sector(Lba, secNum, Buffer);
472 }
473 else if (offset < g_chain->real_img_size_in_bytes)
474 {
475 TmpNum = (g_chain->real_img_size_in_bytes - offset) / 2048;
476 ventoy_read_iso_sector(Lba, TmpNum, Buffer);
477
478 Lba += TmpNum;
479 secNum -= TmpNum;
480 Buffer = (UINT8 *)Buffer + (g_chain->real_img_size_in_bytes - offset);
481 offset = Lba * 2048;
482 }
483
484 VirtSec = g_chain->virt_img_size_in_bytes / 2048;
485 if (Lba >= VirtSec)
486 {
487 return EFI_SUCCESS;
488 }
489 else if (Lba + secNum > VirtSec)
490 {
491 secNum = VirtSec - Lba;
492 }
493
494 debug("XXX block_io_read_real sector:%u count:%u Buffer:%p", (UINT32)Lba, (UINT32)BufferSize / 2048, Buffer);
495
496 if (secNum > g_sector_flag_num)
497 {
498 cur_flag = AllocatePool(secNum * sizeof(ventoy_sector_flag));
499 if (NULL == cur_flag)
500 {
501 return EFI_OUT_OF_RESOURCES;
502 }
503
504 FreePool(g_sector_flag);
505 g_sector_flag = cur_flag;
506 g_sector_flag_num = secNum;
507 }
508
509 for (curlba = Lba, cur_flag = g_sector_flag, j = 0; j < secNum; j++, curlba++, cur_flag++)
510 {
511 cur_flag->flag = 0;
512 for (node = g_virt_chunk, i = 0; i < g_virt_chunk_num; i++, node++)
513 {
514 if (curlba >= node->mem_sector_start && curlba < node->mem_sector_end)
515 {
516 CopyMem((UINT8 *)Buffer + j * 2048,
517 (char *)g_virt_chunk + node->mem_sector_offset + (curlba - node->mem_sector_start) * 2048,
518 2048);
519 cur_flag->flag = 1;
520 break;
521 }
522 else if (curlba >= node->remap_sector_start && curlba < node->remap_sector_end)
523 {
524 cur_flag->remap_lba = node->org_sector_start + curlba - node->remap_sector_start;
525 cur_flag->flag = 2;
526 break;
527 }
528 }
529 }
530
531 for (curlba = Lba, cur_flag = g_sector_flag, j = 0; j < secNum; j++, curlba++, cur_flag++)
532 {
533 if (cur_flag->flag == 2)
534 {
535 if (lastlba == 0)
536 {
537 lastbuffer = (UINT8 *)Buffer + j * 2048;
538 lastlba = cur_flag->remap_lba;
539 lbacount = 1;
540 }
541 else if (lastlba + lbacount == cur_flag->remap_lba)
542 {
543 lbacount++;
544 }
545 else
546 {
547 ventoy_read_iso_sector(lastlba, lbacount, lastbuffer);
548 lastbuffer = (UINT8 *)Buffer + j * 2048;
549 lastlba = cur_flag->remap_lba;
550 lbacount = 1;
551 }
552 }
553 }
554
555 if (lbacount > 0)
556 {
557 ventoy_read_iso_sector(lastlba, lbacount, lastbuffer);
558 }
559
560 return EFI_SUCCESS;
561 }
562
563 EFI_STATUS EFIAPI ventoy_block_io_read
564 (
565 IN EFI_BLOCK_IO_PROTOCOL *This,
566 IN UINT32 MediaId,
567 IN EFI_LBA Lba,
568 IN UINTN BufferSize,
569 OUT VOID *Buffer
570 )
571 {
572 UINT32 IoAlign = 0;
573 VOID *NewBuf = NULL;
574 EFI_STATUS Status = EFI_OUT_OF_RESOURCES;
575
576 if (gBlockData.pRawBlockIo && gBlockData.pRawBlockIo->Media)
577 {
578 IoAlign = gBlockData.pRawBlockIo->Media->IoAlign;
579 }
580
581 if ((IoAlign == 0) || (((UINTN) Buffer & (IoAlign - 1)) == 0))
582 {
583 Status = ventoy_block_io_read_real(This, MediaId, Lba, BufferSize, Buffer);
584 }
585 else
586 {
587 NewBuf = AllocatePages(EFI_SIZE_TO_PAGES(BufferSize + IoAlign));
588 if (NewBuf)
589 {
590 Status = ventoy_block_io_read_real(This, MediaId, Lba, BufferSize, NewBuf);
591 CopyMem(Buffer, NewBuf, BufferSize);
592 FreePages(NewBuf, EFI_SIZE_TO_PAGES(BufferSize + IoAlign));
593 }
594 }
595
596 return Status;
597 }
598
599 EFI_STATUS EFIAPI ventoy_block_io_write
600 (
601 IN EFI_BLOCK_IO_PROTOCOL *This,
602 IN UINT32 MediaId,
603 IN EFI_LBA Lba,
604 IN UINTN BufferSize,
605 IN VOID *Buffer
606 )
607 {
608 UINT32 secNum = 0;
609 UINT64 offset = 0;
610
611 (VOID)This;
612 (VOID)MediaId;
613
614 if (!gSector512Mode)
615 {
616 return EFI_WRITE_PROTECTED;
617 }
618
619 secNum = BufferSize / 2048;
620 offset = Lba * 2048;
621
622 return ventoy_write_iso_sector(Lba, secNum, Buffer);
623 }
624
625 EFI_STATUS EFIAPI ventoy_block_io_flush(IN EFI_BLOCK_IO_PROTOCOL *This)
626 {
627 (VOID)This;
628 return EFI_SUCCESS;
629 }
630
631 STATIC UINTN ventoy_get_current_device_path_id(VOID)
632 {
633 UINTN i = 0;
634 UINTN Count = 0;
635 UINTN MaxId = 0;
636 UINTN CurId = 0;
637 BOOLEAN Find = FALSE;
638 EFI_HANDLE *Handles = NULL;
639 EFI_STATUS Status = EFI_SUCCESS;
640 EFI_DEVICE_PATH_PROTOCOL *DevicePath = NULL;
641 VENDOR_DEVICE_PATH *venPath = NULL;
642
643 Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiDevicePathProtocolGuid,
644 NULL, &Count, &Handles);
645 if (EFI_ERROR(Status))
646 {
647 return 0;
648 }
649
650 for (i = 0; i < Count; i++)
651 {
652 Status = gBS->HandleProtocol(Handles[i], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePath);
653 if (EFI_ERROR(Status))
654 {
655 continue;
656 }
657
658 if (DevicePath->Type == HARDWARE_DEVICE_PATH && DevicePath->SubType == HW_VENDOR_DP)
659 {
660 venPath = (VENDOR_DEVICE_PATH *)DevicePath;
661 if (CompareGuid(&venPath->Guid, &gVtoyBlockDevicePathGuid))
662 {
663 CurId = StrDecimalToUintn((CHAR16 *)(venPath + 1) + StrLen(L"ventoy_"));
664 MaxId = MAX(MaxId, CurId);
665 Find = TRUE;
666 }
667 }
668 }
669
670 FreePool(Handles);
671
672 return Find ? (MaxId + 1) : 0;
673 }
674
675 EFI_STATUS EFIAPI ventoy_fill_device_path(VOID)
676 {
677 UINTN CurVtoyDpId = 0;
678 UINTN NameLen = 0;
679 UINT8 TmpBuf[128] = {0};
680 VENDOR_DEVICE_PATH *venPath = NULL;
681 CHAR16 VtoyDpName[32];
682
683 CurVtoyDpId = ventoy_get_current_device_path_id();
684 UnicodeSPrintAsciiFormat(VtoyDpName, sizeof(VtoyDpName), "ventoy_%03lu", CurVtoyDpId);
685
686 venPath = (VENDOR_DEVICE_PATH *)TmpBuf;
687 NameLen = StrSize(VtoyDpName);
688 venPath->Header.Type = HARDWARE_DEVICE_PATH;
689 venPath->Header.SubType = HW_VENDOR_DP;
690 venPath->Header.Length[0] = sizeof(VENDOR_DEVICE_PATH) + NameLen;
691 venPath->Header.Length[1] = 0;
692 CopyMem(&venPath->Guid, &gVtoyBlockDevicePathGuid, sizeof(EFI_GUID));
693 CopyMem(venPath + 1, VtoyDpName, NameLen);
694
695 gBlockData.Path = AppendDevicePathNode(NULL, (EFI_DEVICE_PATH_PROTOCOL *)TmpBuf);
696 gBlockData.DevicePathCompareLen = sizeof(VENDOR_DEVICE_PATH) + NameLen;
697
698 debug("gBlockData.Path=<%lu><%s>\n", CurVtoyDpId, ConvertDevicePathToText(gBlockData.Path, FALSE, FALSE));
699
700 return EFI_SUCCESS;
701 }
702
703 EFI_STATUS EFIAPI ventoy_connect_driver(IN EFI_HANDLE ControllerHandle, IN CONST CHAR16 *DrvName)
704 {
705 UINTN i = 0;
706 UINTN Count = 0;
707 CHAR16 *DriverName = NULL;
708 EFI_HANDLE *Handles = NULL;
709 EFI_HANDLE DrvHandles[2] = { NULL };
710 EFI_STATUS Status = EFI_SUCCESS;
711 EFI_COMPONENT_NAME_PROTOCOL *NameProtocol = NULL;
712 EFI_COMPONENT_NAME2_PROTOCOL *Name2Protocol = NULL;
713
714 debug("ventoy_connect_driver <%s>...", DrvName);
715
716 Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiComponentName2ProtocolGuid,
717 NULL, &Count, &Handles);
718 if (EFI_ERROR(Status))
719 {
720 return Status;
721 }
722
723 for (i = 0; i < Count; i++)
724 {
725 Status = gBS->HandleProtocol(Handles[i], &gEfiComponentName2ProtocolGuid, (VOID **)&Name2Protocol);
726 if (EFI_ERROR(Status))
727 {
728 continue;
729 }
730
731 VENTOY_GET_COMPONENT_NAME(Name2Protocol, DriverName);
732
733 if (StrStr(DriverName, DrvName))
734 {
735 debug("Find driver name2:<%s>: <%s>", DriverName, DrvName);
736 DrvHandles[0] = Handles[i];
737 break;
738 }
739 }
740
741 if (i < Count)
742 {
743 Status = gBS->ConnectController(ControllerHandle, DrvHandles, NULL, TRUE);
744 debug("ventoy_connect_driver:<%s> <%r>", DrvName, Status);
745 goto end;
746 }
747
748 debug("%s NOT found, now try COMPONENT_NAME", DrvName);
749
750 Count = 0;
751 FreePool(Handles);
752 Handles = NULL;
753
754 Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiComponentNameProtocolGuid,
755 NULL, &Count, &Handles);
756 if (EFI_ERROR(Status))
757 {
758 return Status;
759 }
760
761 for (i = 0; i < Count; i++)
762 {
763 Status = gBS->HandleProtocol(Handles[i], &gEfiComponentNameProtocolGuid, (VOID **)&NameProtocol);
764 if (EFI_ERROR(Status))
765 {
766 continue;
767 }
768
769 VENTOY_GET_COMPONENT_NAME(NameProtocol, DriverName);
770
771 if (StrStr(DriverName, DrvName))
772 {
773 debug("Find driver name:<%s>: <%s>", DriverName, DrvName);
774 DrvHandles[0] = Handles[i];
775 break;
776 }
777 }
778
779 if (i < Count)
780 {
781 Status = gBS->ConnectController(ControllerHandle, DrvHandles, NULL, TRUE);
782 debug("ventoy_connect_driver:<%s> <%r>", DrvName, Status);
783 goto end;
784 }
785
786 Status = EFI_NOT_FOUND;
787
788 end:
789 FreePool(Handles);
790
791 return Status;
792 }
793
794
795 STATIC BOOLEAN ventoy_filesystem_need_wrapper(IN CONST CHAR16 *DrvName)
796 {
797 UINTN i;
798 CHAR16 UpperDrvName[256];
799
800 StrCpyS(UpperDrvName, 256, DrvName);
801
802 for (i = 0; i < 256 && UpperDrvName[i]; i++)
803 {
804 if (UpperDrvName[i] >= 'a' && UpperDrvName[i] <= 'z')
805 {
806 UpperDrvName[i] = 'A' + (UpperDrvName[i] - 'a');
807 }
808 }
809
810 /*
811 * suppress some file system drivers
812 * 1. rEFInd File System Driver
813 *
814 */
815
816 if (StrStr(UpperDrvName, L"REFIND") && StrStr(UpperDrvName, L"FILE SYSTEM"))
817 {
818 return TRUE;
819 }
820
821 return FALSE;
822 }
823
824 STATIC VOID ventoy_add_filesystem_wrapper
825 (
826 IN EFI_DRIVER_BINDING_PROTOCOL *DriverBindProtocol,
827 IN CONST CHAR16 *DriverName
828 )
829 {
830 UINTN j;
831
832 if (g_DriverBindWrapperCnt >= MAX_DRIVER_BIND_WRAPPER)
833 {
834 debug("driver binding wrapper overflow %lu", g_DriverBindWrapperCnt);
835 return;
836 }
837
838 if (!ventoy_filesystem_need_wrapper(DriverName))
839 {
840 return;
841 }
842
843 for (j = 0; j < g_DriverBindWrapperCnt; j++)
844 {
845 if (g_DriverBindWrapperList[j].DriverBinding == DriverBindProtocol)
846 {
847 debug("Duplicate driverbinding <%s> %p %lu %lu", DriverName, DriverBindProtocol, j, g_DriverBindWrapperCnt);
848 break;
849 }
850 }
851
852 if (j >= g_DriverBindWrapperCnt)
853 {
854 g_DriverBindWrapperList[g_DriverBindWrapperCnt].DriverBinding = DriverBindProtocol;
855 g_DriverBindWrapperList[g_DriverBindWrapperCnt].pfOldSupport = DriverBindProtocol->Supported;
856 g_DriverBindWrapperCnt++;
857 debug("Add driverbinding <%s> %p %lu", DriverName, DriverBindProtocol, g_DriverBindWrapperCnt);
858 }
859 }
860
861 STATIC EFI_STATUS ventoy_find_filesystem_driverbind(VOID)
862 {
863 UINTN i = 0;
864 UINTN Count = 0;
865 CHAR16 *DriverName = NULL;
866 EFI_HANDLE *Handles = NULL;
867 EFI_STATUS Status = EFI_SUCCESS;
868 EFI_COMPONENT_NAME_PROTOCOL *NameProtocol = NULL;
869 EFI_COMPONENT_NAME2_PROTOCOL *Name2Protocol = NULL;
870 EFI_DRIVER_BINDING_PROTOCOL *DriverBindProtocol = NULL;
871
872 debug("ventoy_find_filesystem_driverbind...");
873
874 Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiComponentName2ProtocolGuid,
875 NULL, &Count, &Handles);
876 if (EFI_ERROR(Status))
877 {
878 return Status;
879 }
880
881 for (i = 0; i < Count; i++)
882 {
883 Status = gBS->HandleProtocol(Handles[i], &gEfiComponentName2ProtocolGuid, (VOID **)&Name2Protocol);
884 if (EFI_ERROR(Status))
885 {
886 continue;
887 }
888
889 VENTOY_GET_COMPONENT_NAME(Name2Protocol, DriverName);
890
891 Status = gBS->HandleProtocol(Handles[i], &gEfiDriverBindingProtocolGuid, (VOID **)&DriverBindProtocol);
892 if (EFI_ERROR(Status))
893 {
894 debug("### 2 No DriverBind <%s> <%r>", DriverName, Status);
895 continue;
896 }
897
898 ventoy_add_filesystem_wrapper(DriverBindProtocol, DriverName);
899 }
900
901 Count = 0;
902 FreePool(Handles);
903 Handles = NULL;
904
905 Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiComponentNameProtocolGuid,
906 NULL, &Count, &Handles);
907 if (EFI_ERROR(Status))
908 {
909 return Status;
910 }
911
912 for (i = 0; i < Count; i++)
913 {
914 Status = gBS->HandleProtocol(Handles[i], &gEfiComponentNameProtocolGuid, (VOID **)&NameProtocol);
915 if (EFI_ERROR(Status))
916 {
917 continue;
918 }
919
920 VENTOY_GET_COMPONENT_NAME(NameProtocol, DriverName);
921
922 Status = gBS->HandleProtocol(Handles[i], &gEfiDriverBindingProtocolGuid, (VOID **)&DriverBindProtocol);
923 if (EFI_ERROR(Status))
924 {
925 debug("### 1 No DriverBind <%s> <%r>", DriverName, Status);
926 continue;
927 }
928
929 ventoy_add_filesystem_wrapper(DriverBindProtocol, DriverName);
930 }
931
932 FreePool(Handles);
933
934 return EFI_SUCCESS;
935 }
936
937 STATIC EFI_STATUS EFIAPI ventoy_wrapper_driver_bind_support
938 (
939 IN EFI_DRIVER_BINDING_PROTOCOL *This,
940 IN EFI_HANDLE ControllerHandle,
941 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
942 )
943 {
944 UINTN i;
945 EFI_STATUS Status = EFI_SUCCESS;
946 EFI_DEVICE_PATH_PROTOCOL *DevicePath = NULL;
947 EFI_DRIVER_BINDING_SUPPORTED pfOldSupport = NULL;
948
949 for (i = 0; i < g_DriverBindWrapperCnt; i++)
950 {
951 if (g_DriverBindWrapperList[i].DriverBinding == This)
952 {
953 pfOldSupport = g_DriverBindWrapperList[i].pfOldSupport;
954 break;
955 }
956 }
957
958 debug("ventoy_wrapper_driver_bind_support %lu %p", i, pfOldSupport);
959
960 if (!pfOldSupport)
961 {
962 return EFI_UNSUPPORTED;
963 }
964
965 Status = gBS->HandleProtocol(ControllerHandle, &gEfiDevicePathProtocolGuid, (VOID **)&DevicePath);
966 if (EFI_ERROR(Status))
967 {
968 goto out;
969 }
970
971 if (0 == CompareMem(gBlockData.Path, DevicePath, gBlockData.DevicePathCompareLen))
972 {
973 debug("return EFI_UNSUPPORTED for ventoy");
974 return EFI_UNSUPPORTED;
975 }
976
977 out:
978 return pfOldSupport(This, ControllerHandle, RemainingDevicePath);
979 }
980
981 EFI_STATUS ventoy_disable_ex_filesystem(VOID)
982 {
983 UINTN i;
984
985 ventoy_find_filesystem_driverbind();
986
987 for (i = 0; i < g_DriverBindWrapperCnt; i++)
988 {
989 g_DriverBindWrapperList[i].DriverBinding->Supported = ventoy_wrapper_driver_bind_support;
990 }
991
992 debug("Wrapper Ex Driver Binding %lu", g_DriverBindWrapperCnt);
993 ventoy_debug_pause();
994
995 return EFI_SUCCESS;
996 }
997
998 EFI_STATUS ventoy_enable_ex_filesystem(VOID)
999 {
1000 UINTN i;
1001
1002 for (i = 0; i < g_DriverBindWrapperCnt; i++)
1003 {
1004 g_DriverBindWrapperList[i].DriverBinding->Supported = g_DriverBindWrapperList[i].pfOldSupport;
1005 }
1006 g_DriverBindWrapperCnt = 0;
1007
1008 return EFI_SUCCESS;
1009 }
1010
1011 EFI_STATUS EFIAPI ventoy_block_io_read_512
1012 (
1013 IN EFI_BLOCK_IO_PROTOCOL *This,
1014 IN UINT32 MediaId,
1015 IN EFI_LBA Lba,
1016 IN UINTN BufferSize,
1017 OUT VOID *Buffer
1018 )
1019 {
1020 EFI_LBA Mod;
1021 UINTN ReadSize;
1022 UINT8 *CurBuf = NULL;
1023 EFI_STATUS Status = EFI_SUCCESS;
1024
1025 debug("ventoy_block_io_read_512 %lu %lu Buffer:%p\n", Lba, BufferSize / 512, Buffer);
1026
1027 CurBuf = (UINT8 *)Buffer;
1028
1029 Mod = Lba % 4;
1030 if (Mod > 0)
1031 {
1032 Status |= g_sector_2048_read(This, MediaId, Lba / 4, 2048, g_sector_buf);
1033
1034 if (BufferSize <= (4 - Mod) * 512)
1035 {
1036 CopyMem(CurBuf, g_sector_buf + Mod * 512, BufferSize);
1037 return EFI_SUCCESS;
1038 }
1039 else
1040 {
1041 ReadSize = (4 - Mod) * 512;
1042 CopyMem(CurBuf, g_sector_buf + Mod * 512, ReadSize);
1043 CurBuf += ReadSize;
1044 Lba += (4 - Mod);
1045 BufferSize -= ReadSize;
1046 }
1047 }
1048
1049 if (BufferSize >= 2048)
1050 {
1051 ReadSize = BufferSize / 2048 * 2048;
1052
1053 Status |= g_sector_2048_read(This, MediaId, Lba / 4, ReadSize, CurBuf);
1054 CurBuf += ReadSize;
1055
1056 Lba += ReadSize / 512;
1057 BufferSize -= ReadSize;
1058 }
1059
1060 if (BufferSize > 0)
1061 {
1062 Status |= g_sector_2048_read(This, MediaId, Lba / 4, 2048, g_sector_buf);
1063 CopyMem(CurBuf, g_sector_buf, BufferSize);
1064 }
1065
1066 return Status;
1067 }
1068
1069 EFI_STATUS EFIAPI ventoy_block_io_write_512
1070 (
1071 IN EFI_BLOCK_IO_PROTOCOL *This,
1072 IN UINT32 MediaId,
1073 IN EFI_LBA Lba,
1074 IN UINTN BufferSize,
1075 IN VOID *Buffer
1076 )
1077 {
1078 EFI_LBA Mod;
1079 UINTN ReadSize;
1080 UINT8 *CurBuf = NULL;
1081 EFI_STATUS Status = EFI_SUCCESS;
1082
1083 debug("ventoy_block_io_write_512 %lu %lu\n", Lba, BufferSize / 512);
1084
1085 CurBuf = (UINT8 *)Buffer;
1086
1087 Mod = Lba % 4;
1088 if (Mod > 0)
1089 {
1090 Status |= g_sector_2048_read(This, MediaId, Lba / 4, 2048, g_sector_buf);
1091
1092 if (BufferSize <= (4 - Mod) * 512)
1093 {
1094 CopyMem(g_sector_buf + Mod * 512, CurBuf, BufferSize);
1095 return g_sector_2048_write(This, MediaId, Lba / 4, 2048, g_sector_buf);
1096 }
1097 else
1098 {
1099 ReadSize = (4 - Mod) * 512;
1100 CopyMem(g_sector_buf + Mod * 512, CurBuf, ReadSize);
1101 g_sector_2048_write(This, MediaId, Lba / 4, 2048, g_sector_buf);
1102
1103 CurBuf += ReadSize;
1104 Lba += (4 - Mod);
1105 BufferSize -= ReadSize;
1106 }
1107 }
1108
1109 if (BufferSize >= 2048)
1110 {
1111 ReadSize = BufferSize / 2048 * 2048;
1112
1113 Status |= g_sector_2048_write(This, MediaId, Lba / 4, ReadSize, CurBuf);
1114 CurBuf += ReadSize;
1115
1116 Lba += ReadSize / 512;
1117 BufferSize -= ReadSize;
1118 }
1119
1120 if (BufferSize > 0)
1121 {
1122 Status |= g_sector_2048_read(This, MediaId, Lba / 4, 2048, g_sector_buf);
1123
1124 CopyMem(g_sector_buf, CurBuf, BufferSize);
1125 g_sector_2048_write(This, MediaId, Lba / 4, 2048, g_sector_buf);
1126 }
1127
1128 return Status;
1129 }
1130
1131 EFI_STATUS EFIAPI ventoy_install_blockio(IN EFI_HANDLE ImageHandle, IN UINT64 ImgSize)
1132 {
1133 EFI_STATUS Status = EFI_SUCCESS;
1134 EFI_BLOCK_IO_PROTOCOL *pBlockIo = &(gBlockData.BlockIo);
1135
1136 ventoy_fill_device_path();
1137
1138 debug("install block io protocol %p", ImageHandle);
1139 ventoy_debug_pause();
1140
1141 if (gSector512Mode)
1142 {
1143 gBlockData.Media.BlockSize = 512;
1144 gBlockData.Media.LastBlock = ImgSize / 512 - 1;
1145 gBlockData.Media.ReadOnly = FALSE;
1146 }
1147 else
1148 {
1149 gBlockData.Media.BlockSize = 2048;
1150 gBlockData.Media.LastBlock = ImgSize / 2048 - 1;
1151 gBlockData.Media.ReadOnly = TRUE;
1152 }
1153
1154 gBlockData.Media.MediaPresent = 1;
1155 gBlockData.Media.LogicalBlocksPerPhysicalBlock = 1;
1156
1157 pBlockIo->Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3;
1158 pBlockIo->Media = &(gBlockData.Media);
1159 pBlockIo->Reset = ventoy_block_io_reset;
1160
1161 if (gSector512Mode)
1162 {
1163 g_sector_2048_read = gMemdiskMode ? ventoy_block_io_ramdisk_read : ventoy_block_io_read;
1164 g_sector_2048_write = gMemdiskMode ? ventoy_block_io_ramdisk_write : ventoy_block_io_write;
1165 pBlockIo->ReadBlocks = ventoy_block_io_read_512;
1166 pBlockIo->WriteBlocks = ventoy_block_io_write_512;
1167 }
1168 else
1169 {
1170 pBlockIo->ReadBlocks = gMemdiskMode ? ventoy_block_io_ramdisk_read : ventoy_block_io_read;
1171 pBlockIo->WriteBlocks = ventoy_block_io_write;
1172 }
1173
1174 pBlockIo->FlushBlocks = ventoy_block_io_flush;
1175
1176 Status = gBS->InstallMultipleProtocolInterfaces(&gBlockData.Handle,
1177 &gEfiBlockIoProtocolGuid, &gBlockData.BlockIo,
1178 &gEfiDevicePathProtocolGuid, gBlockData.Path,
1179 NULL);
1180 debug("Install protocol %r %p", Status, gBlockData.Handle);
1181 if (EFI_ERROR(Status))
1182 {
1183 return Status;
1184 }
1185
1186 Status = ventoy_connect_driver(gBlockData.Handle, L"Disk I/O Driver");
1187 debug("Connect disk IO driver %r", Status);
1188
1189 Status = ventoy_connect_driver(gBlockData.Handle, L"Partition Driver");
1190 debug("Connect partition driver %r", Status);
1191 if (EFI_ERROR(Status))
1192 {
1193 Status = gBS->ConnectController(gBlockData.Handle, NULL, NULL, TRUE);
1194 debug("Connect all controller %r", Status);
1195 }
1196
1197 ventoy_debug_pause();
1198
1199 return EFI_SUCCESS;
1200 }
1201
1202 #if 0
1203 /* For file replace */
1204 #endif
1205
1206 STATIC EFI_STATUS EFIAPI
1207 ventoy_wrapper_fs_open(EFI_FILE_HANDLE This, EFI_FILE_HANDLE *New, CHAR16 *Name, UINT64 Mode, UINT64 Attributes)
1208 {
1209 (VOID)This;
1210 (VOID)New;
1211 (VOID)Name;
1212 (VOID)Mode;
1213 (VOID)Attributes;
1214 return EFI_SUCCESS;
1215 }
1216
1217 STATIC EFI_STATUS EFIAPI
1218 ventoy_wrapper_file_open_ex(EFI_FILE_HANDLE This, EFI_FILE_HANDLE *New, CHAR16 *Name, UINT64 Mode, UINT64 Attributes, EFI_FILE_IO_TOKEN *Token)
1219 {
1220 return ventoy_wrapper_fs_open(This, New, Name, Mode, Attributes);
1221 }
1222
1223 STATIC EFI_STATUS EFIAPI
1224 ventoy_wrapper_file_delete(EFI_FILE_HANDLE This)
1225 {
1226 (VOID)This;
1227 return EFI_SUCCESS;
1228 }
1229
1230 STATIC EFI_STATUS EFIAPI
1231 ventoy_wrapper_file_set_info(EFI_FILE_HANDLE This, EFI_GUID *Type, UINTN Len, VOID *Data)
1232 {
1233 return EFI_SUCCESS;
1234 }
1235
1236 STATIC EFI_STATUS EFIAPI
1237 ventoy_wrapper_file_flush(EFI_FILE_HANDLE This)
1238 {
1239 (VOID)This;
1240 return EFI_SUCCESS;
1241 }
1242
1243 /* Ex version */
1244 STATIC EFI_STATUS EFIAPI
1245 ventoy_wrapper_file_flush_ex(EFI_FILE_HANDLE This, EFI_FILE_IO_TOKEN *Token)
1246 {
1247 (VOID)This;
1248 (VOID)Token;
1249 return EFI_SUCCESS;
1250 }
1251
1252 /* Ex version */
1253 STATIC EFI_STATUS EFIAPI
1254 ventoy_wrapper_file_flush_ex_img(EFI_FILE_HANDLE This, EFI_FILE_IO_TOKEN *Token)
1255 {
1256 (VOID)This;
1257 (VOID)Token;
1258 return EFI_SUCCESS;
1259 }
1260
1261
1262 STATIC EFI_STATUS EFIAPI
1263 ventoy_wrapper_file_write(EFI_FILE_HANDLE This, UINTN *Len, VOID *Data)
1264 {
1265 (VOID)This;
1266 (VOID)Len;
1267 (VOID)Data;
1268
1269 return EFI_WRITE_PROTECTED;
1270 }
1271
1272 STATIC EFI_STATUS EFIAPI
1273 ventoy_wrapper_file_write_ex(IN EFI_FILE_PROTOCOL *This, IN OUT EFI_FILE_IO_TOKEN *Token)
1274 {
1275 return ventoy_wrapper_file_write(This, &(Token->BufferSize), Token->Buffer);
1276 }
1277
1278
1279 STATIC EFI_STATUS EFIAPI
1280 ventoy_wrapper_file_close(EFI_FILE_HANDLE This)
1281 {
1282 (VOID)This;
1283 return EFI_SUCCESS;
1284 }
1285
1286 STATIC EFI_STATUS EFIAPI
1287 ventoy_wrapper_file_set_pos(EFI_FILE_HANDLE This, UINT64 Position)
1288 {
1289 ventoy_efi_file_replace *replace = NULL;
1290
1291 ASSIGN_REPLACE(This, replace);
1292
1293 if (Position <= replace->FileSizeBytes)
1294 {
1295 replace->CurPos = Position;
1296 }
1297 else
1298 {
1299 replace->CurPos = replace->FileSizeBytes;
1300 }
1301
1302 return EFI_SUCCESS;
1303 }
1304
1305 STATIC EFI_STATUS EFIAPI
1306 ventoy_wrapper_file_get_pos(EFI_FILE_HANDLE This, UINT64 *Position)
1307 {
1308 ventoy_efi_file_replace *replace = NULL;
1309
1310 ASSIGN_REPLACE(This, replace);
1311
1312 *Position = replace->CurPos;
1313
1314 return EFI_SUCCESS;
1315 }
1316
1317
1318 STATIC EFI_STATUS EFIAPI
1319 ventoy_wrapper_file_get_info(EFI_FILE_HANDLE This, EFI_GUID *Type, UINTN *Len, VOID *Data)
1320 {
1321 EFI_FILE_INFO *Info = (EFI_FILE_INFO *) Data;
1322 ventoy_efi_file_replace *replace = NULL;
1323
1324 ASSIGN_REPLACE(This, replace);
1325
1326 debug("ventoy_wrapper_file_get_info ... %u", *Len);
1327
1328 if (!CompareGuid(Type, &gEfiFileInfoGuid))
1329 {
1330 return EFI_INVALID_PARAMETER;
1331 }
1332
1333 if (*Len == 0)
1334 {
1335 *Len = 384;
1336 return EFI_BUFFER_TOO_SMALL;
1337 }
1338
1339 ZeroMem(Data, sizeof(EFI_FILE_INFO));
1340
1341 Info->Size = sizeof(EFI_FILE_INFO);
1342 Info->FileSize = replace->FileSizeBytes;
1343 Info->PhysicalSize = replace->FileSizeBytes;
1344 Info->Attribute = EFI_FILE_READ_ONLY;
1345 //Info->FileName = EFI_FILE_READ_ONLY;
1346
1347 *Len = Info->Size;
1348
1349 return EFI_SUCCESS;
1350 }
1351
1352 STATIC EFI_STATUS EFIAPI
1353 ventoy_wrapper_file_read(EFI_FILE_HANDLE This, UINTN *Len, VOID *Data)
1354 {
1355 EFI_LBA Lba;
1356 UINTN ReadLen = *Len;
1357 ventoy_efi_file_replace *replace = NULL;
1358
1359 ASSIGN_REPLACE(This, replace);
1360
1361 debug("ventoy_wrapper_file_read ... %u", *Len);
1362
1363 if (replace->CurPos + ReadLen > replace->FileSizeBytes)
1364 {
1365 ReadLen = replace->FileSizeBytes - replace->CurPos;
1366 }
1367
1368 Lba = replace->CurPos / 2048 + replace->BlockIoSectorStart;
1369
1370 ventoy_block_io_read(NULL, 0, Lba, ReadLen, Data);
1371
1372 *Len = ReadLen;
1373
1374 replace->CurPos += ReadLen;
1375
1376 return EFI_SUCCESS;
1377 }
1378
1379 STATIC EFI_STATUS EFIAPI
1380 ventoy_wrapper_file_read_ex(IN EFI_FILE_PROTOCOL *This, IN OUT EFI_FILE_IO_TOKEN *Token)
1381 {
1382 return ventoy_wrapper_file_read(This, &(Token->BufferSize), Token->Buffer);
1383 }
1384
1385 STATIC EFI_STATUS EFIAPI ventoy_wrapper_file_procotol(EFI_FILE_PROTOCOL *File, BOOLEAN Img)
1386 {
1387 File->Revision = EFI_FILE_PROTOCOL_REVISION2;
1388 File->Open = ventoy_wrapper_fs_open;
1389 File->Close = ventoy_wrapper_file_close;
1390 File->Delete = ventoy_wrapper_file_delete;
1391 File->Read = ventoy_wrapper_file_read;
1392 File->Write = ventoy_wrapper_file_write;
1393 File->GetPosition = ventoy_wrapper_file_get_pos;
1394 File->SetPosition = ventoy_wrapper_file_set_pos;
1395 File->GetInfo = ventoy_wrapper_file_get_info;
1396 File->SetInfo = ventoy_wrapper_file_set_info;
1397 File->Flush = ventoy_wrapper_file_flush;
1398 File->OpenEx = ventoy_wrapper_file_open_ex;
1399 File->ReadEx = ventoy_wrapper_file_read_ex;
1400 File->WriteEx = ventoy_wrapper_file_write_ex;
1401 File->FlushEx = Img ? ventoy_wrapper_file_flush_ex_img : ventoy_wrapper_file_flush_ex;
1402
1403 return EFI_SUCCESS;
1404 }
1405
1406 STATIC EFI_STATUS EFIAPI ventoy_wrapper_file_open
1407 (
1408 EFI_FILE_HANDLE This,
1409 EFI_FILE_HANDLE *New,
1410 CHAR16 *Name,
1411 UINT64 Mode,
1412 UINT64 Attributes
1413 )
1414 {
1415 UINT32 i = 0;
1416 UINT32 j = 0;
1417 UINT64 Sectors = 0;
1418 EFI_STATUS Status = EFI_SUCCESS;
1419 CHAR8 TmpName[256];
1420 CHAR8 OldName[256];
1421 ventoy_virt_chunk *virt = NULL;
1422
1423 debug("## ventoy_wrapper_file_open <%s> ", Name);
1424
1425 if ((Mode & EFI_FILE_MODE_WRITE) > 0 && StrCmp(Name, L"\\loader\\random-seed") == 0)
1426 {
1427 if (gDebugPrint)
1428 {
1429 debug("## ventoy_wrapper_file_open return NOT_FOUND for random-seed %lx", Mode);
1430 sleep(3);
1431 }
1432 return EFI_NOT_FOUND;
1433 }
1434
1435 Status = g_original_fopen(This, New, Name, Mode, Attributes);
1436 if (EFI_ERROR(Status))
1437 {
1438 return Status;
1439 }
1440
1441
1442 if (g_file_replace_list && g_file_replace_list->magic == GRUB_FILE_REPLACE_MAGIC &&
1443 g_file_replace_list->new_file_virtual_id < g_virt_chunk_num)
1444 {
1445 AsciiSPrint(TmpName, sizeof(TmpName), "%s", Name);
1446 for (j = 0; j < 4; j++)
1447 {
1448 if (0 == AsciiStriCmp(g_file_replace_list[i].old_file_name[j], TmpName))
1449 {
1450 g_original_fclose(*New);
1451 *New = &g_efi_file_replace.WrapperHandle;
1452 ventoy_wrapper_file_procotol(*New, FALSE);
1453
1454 virt = g_virt_chunk + g_file_replace_list->new_file_virtual_id;
1455
1456 Sectors = (virt->mem_sector_end - virt->mem_sector_start) + (virt->remap_sector_end - virt->remap_sector_start);
1457
1458 g_efi_file_replace.BlockIoSectorStart = virt->mem_sector_start;
1459 g_efi_file_replace.FileSizeBytes = Sectors * 2048;
1460
1461 if (gDebugPrint)
1462 {
1463 debug("## ventoy_wrapper_file_open <%s> BlockStart:%lu Sectors:%lu Bytes:%lu", Name,
1464 g_efi_file_replace.BlockIoSectorStart, Sectors, Sectors * 2048);
1465 sleep(3);
1466 }
1467
1468 return Status;
1469 }
1470 }
1471
1472 if (StrCmp(Name, L"\\EFI\\BOOT") == 0)
1473 {
1474 (*New)->Open = ventoy_wrapper_file_open;
1475 }
1476 }
1477
1478
1479
1480 if (g_img_replace_list && g_img_replace_list->magic == GRUB_IMG_REPLACE_MAGIC &&
1481 g_img_replace_list->new_file_virtual_id < g_virt_chunk_num)
1482 {
1483 AsciiSPrint(TmpName, sizeof(TmpName), "%s", Name);
1484 for (j = 0; j < g_img_replace_list->old_file_cnt; j++)
1485 {
1486 AsciiStrCpyS(OldName, sizeof(OldName), g_img_replace_list[i].old_file_name[j]);
1487 if ((0 == AsciiStrCmp(OldName, TmpName)) ||
1488 (AsciiStrnCmp(OldName, "\\loader\\entries\\", 16) == 0 &&
1489 AsciiStrCmp(OldName + 16, TmpName) == 0
1490 )
1491 )
1492 {
1493 g_original_fclose(*New);
1494 *New = &g_img_file_replace.WrapperHandle;
1495 ventoy_wrapper_file_procotol(*New, TRUE);
1496
1497 virt = g_virt_chunk + g_img_replace_list->new_file_virtual_id;
1498
1499 Sectors = (virt->mem_sector_end - virt->mem_sector_start) + (virt->remap_sector_end - virt->remap_sector_start);
1500
1501 g_img_file_replace.BlockIoSectorStart = virt->mem_sector_start;
1502 g_img_file_replace.FileSizeBytes = Sectors * 2048;
1503
1504 if (gDebugPrint)
1505 {
1506 debug("## ventoy_wrapper_file_open2 <%s> BlockStart:%lu Sectors:%lu Bytes:%lu", Name,
1507 g_img_file_replace.BlockIoSectorStart, Sectors, Sectors * 2048);
1508 sleep(3);
1509 }
1510
1511 return Status;
1512 }
1513 }
1514
1515 if (StrCmp(Name, L"\\loader\\entries") == 0)
1516 {
1517 (*New)->Open = ventoy_wrapper_file_open;
1518 }
1519 }
1520
1521 return Status;
1522 }
1523
1524 EFI_STATUS EFIAPI ventoy_wrapper_open_volume
1525 (
1526 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
1527 OUT EFI_FILE_PROTOCOL **Root
1528 )
1529 {
1530 EFI_STATUS Status = EFI_SUCCESS;
1531
1532 Status = g_original_open_volume(This, Root);
1533 if (!EFI_ERROR(Status))
1534 {
1535 g_original_fopen = (*Root)->Open;
1536 g_original_fclose = (*Root)->Close;
1537 (*Root)->Open = ventoy_wrapper_file_open;
1538 }
1539
1540 return Status;
1541 }
1542
1543 EFI_STATUS EFIAPI ventoy_wrapper_push_openvolume(IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME OpenVolume)
1544 {
1545 g_original_open_volume = OpenVolume;
1546 return EFI_SUCCESS;
1547 }
1548
1549 #if 0
1550 /* For auto skip Windows 'Press any key to boot from CD or DVD ...' */
1551 #endif
1552
1553 STATIC EFI_STATUS EFIAPI ventoy_wrapper_read_key_ex
1554 (
1555 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
1556 OUT EFI_KEY_DATA *KeyData
1557 )
1558 {
1559 /* only hook once before BCD file read */
1560 if (g_keyboard_hook_count == 0 && g_blockio_bcd_read_done == FALSE)
1561 {
1562 g_keyboard_hook_count++;
1563
1564 KeyData->Key.ScanCode = SCAN_DELETE;
1565 KeyData->Key.UnicodeChar = 0;
1566 KeyData->KeyState.KeyShiftState = 0;
1567 KeyData->KeyState.KeyToggleState = 0;
1568
1569 return EFI_SUCCESS;
1570 }
1571
1572 return g_org_read_key_ex(This, KeyData);
1573 }
1574
1575 EFI_STATUS EFIAPI ventoy_wrapper_read_key
1576 (
1577 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
1578 OUT EFI_INPUT_KEY *Key
1579 )
1580 {
1581 /* only hook once before BCD file read */
1582 if (g_keyboard_hook_count == 0 && g_blockio_bcd_read_done == FALSE)
1583 {
1584 g_keyboard_hook_count++;
1585
1586 Key->ScanCode = SCAN_DELETE;
1587 Key->UnicodeChar = 0;
1588 return EFI_SUCCESS;
1589 }
1590
1591 return g_org_read_key(This, Key);
1592 }
1593
1594 EFI_STATUS ventoy_hook_keyboard_start(VOID)
1595 {
1596 g_blockio_start_record_bcd = TRUE;
1597 g_blockio_bcd_read_done = FALSE;
1598 g_keyboard_hook_count = 0;
1599
1600 if (g_con_simple_input_ex)
1601 {
1602 g_org_read_key_ex = g_con_simple_input_ex->ReadKeyStrokeEx;
1603 g_con_simple_input_ex->ReadKeyStrokeEx = ventoy_wrapper_read_key_ex;
1604 }
1605
1606 g_org_read_key = gST->ConIn->ReadKeyStroke;
1607 gST->ConIn->ReadKeyStroke = ventoy_wrapper_read_key;
1608
1609 return EFI_SUCCESS;
1610 }
1611
1612 EFI_STATUS ventoy_hook_keyboard_stop(VOID)
1613 {
1614 g_blockio_start_record_bcd = FALSE;
1615 g_blockio_bcd_read_done = FALSE;
1616 g_keyboard_hook_count = 0;
1617
1618 if (g_con_simple_input_ex)
1619 {
1620 g_con_simple_input_ex->ReadKeyStrokeEx = g_org_read_key_ex;
1621 }
1622
1623 gST->ConIn->ReadKeyStroke = g_org_read_key;
1624
1625 return EFI_SUCCESS;
1626 }
1627
1628 #if 0
1629 /* Fixup the 1st cdrom influnce for Windows boot */
1630 #endif
1631
1632 STATIC EFI_STATUS EFIAPI ventoy_wrapper_locate_handle
1633 (
1634 IN EFI_LOCATE_SEARCH_TYPE SearchType,
1635 IN EFI_GUID *Protocol, OPTIONAL
1636 IN VOID *SearchKey, OPTIONAL
1637 IN OUT UINTN *BufferSize,
1638 OUT EFI_HANDLE *Buffer
1639 )
1640 {
1641 UINTN i;
1642 EFI_HANDLE Handle = NULL;
1643 EFI_STATUS Status = EFI_SUCCESS;
1644
1645 Status = g_org_locate_handle(SearchType, Protocol, SearchKey, BufferSize, Buffer);
1646
1647 if (EFI_SUCCESS == Status && Protocol && CompareGuid(&gEfiBlockIoProtocolGuid, Protocol))
1648 {
1649 for (i = 0; i < (*BufferSize) / sizeof(EFI_HANDLE); i++)
1650 {
1651 if (Buffer[i] == gBlockData.Handle)
1652 {
1653 Handle = Buffer[0];
1654 Buffer[0] = Buffer[i];
1655 Buffer[i] = Handle;
1656 break;
1657 }
1658 }
1659 }
1660
1661 return Status;
1662 }
1663
1664 EFI_STATUS ventoy_hook_1st_cdrom_start(VOID)
1665 {
1666 g_org_locate_handle = gBS->LocateHandle;
1667 gBS->LocateHandle = ventoy_wrapper_locate_handle;
1668
1669 return EFI_SUCCESS;
1670 }
1671
1672 EFI_STATUS ventoy_hook_1st_cdrom_stop(VOID)
1673 {
1674 gBS->LocateHandle = g_org_locate_handle;
1675 g_org_locate_handle = NULL;
1676
1677 return EFI_SUCCESS;
1678 }
1679