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