]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/VentoyProtocol.c
293ffc952048a8d221cf4ca94759eb5d369e0f9f
[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"ISO9660") || StrStr(UpperDrvName, L"UDF"))
813 {
814 return TRUE;
815 }
816
817 if (StrStr(UpperDrvName, L"REFIND") && StrStr(UpperDrvName, L"FILE SYSTEM"))
818 {
819 return TRUE;
820 }
821
822 return FALSE;
823 }
824
825 STATIC VOID ventoy_add_filesystem_wrapper
826 (
827 IN EFI_DRIVER_BINDING_PROTOCOL *DriverBindProtocol,
828 IN CONST CHAR16 *DriverName
829 )
830 {
831 UINTN j;
832
833 if (g_DriverBindWrapperCnt >= MAX_DRIVER_BIND_WRAPPER)
834 {
835 debug("driver binding wrapper overflow %lu", g_DriverBindWrapperCnt);
836 return;
837 }
838
839 if (!ventoy_filesystem_need_wrapper(DriverName))
840 {
841 return;
842 }
843
844 for (j = 0; j < g_DriverBindWrapperCnt; j++)
845 {
846 if (g_DriverBindWrapperList[j].DriverBinding == DriverBindProtocol)
847 {
848 debug("Duplicate driverbinding <%s> %p %lu %lu", DriverName, DriverBindProtocol, j, g_DriverBindWrapperCnt);
849 break;
850 }
851 }
852
853 if (j >= g_DriverBindWrapperCnt)
854 {
855 g_DriverBindWrapperList[g_DriverBindWrapperCnt].DriverBinding = DriverBindProtocol;
856 g_DriverBindWrapperList[g_DriverBindWrapperCnt].pfOldSupport = DriverBindProtocol->Supported;
857 g_DriverBindWrapperCnt++;
858 debug("Add driverbinding <%s> %p %lu", DriverName, DriverBindProtocol, g_DriverBindWrapperCnt);
859 }
860 }
861
862 STATIC EFI_STATUS ventoy_find_filesystem_driverbind(VOID)
863 {
864 UINTN i = 0;
865 UINTN Count = 0;
866 CHAR16 *DriverName = NULL;
867 EFI_HANDLE *Handles = NULL;
868 EFI_STATUS Status = EFI_SUCCESS;
869 EFI_COMPONENT_NAME_PROTOCOL *NameProtocol = NULL;
870 EFI_COMPONENT_NAME2_PROTOCOL *Name2Protocol = NULL;
871 EFI_DRIVER_BINDING_PROTOCOL *DriverBindProtocol = NULL;
872
873 debug("ventoy_find_filesystem_driverbind...");
874
875 Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiComponentName2ProtocolGuid,
876 NULL, &Count, &Handles);
877 if (EFI_ERROR(Status))
878 {
879 return Status;
880 }
881
882 for (i = 0; i < Count; i++)
883 {
884 Status = gBS->HandleProtocol(Handles[i], &gEfiComponentName2ProtocolGuid, (VOID **)&Name2Protocol);
885 if (EFI_ERROR(Status))
886 {
887 continue;
888 }
889
890 VENTOY_GET_COMPONENT_NAME(Name2Protocol, DriverName);
891
892 Status = gBS->HandleProtocol(Handles[i], &gEfiDriverBindingProtocolGuid, (VOID **)&DriverBindProtocol);
893 if (EFI_ERROR(Status))
894 {
895 debug("### 2 No DriverBind <%s> <%r>", DriverName, Status);
896 continue;
897 }
898
899 ventoy_add_filesystem_wrapper(DriverBindProtocol, DriverName);
900 }
901
902 Count = 0;
903 FreePool(Handles);
904 Handles = NULL;
905
906 Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiComponentNameProtocolGuid,
907 NULL, &Count, &Handles);
908 if (EFI_ERROR(Status))
909 {
910 return Status;
911 }
912
913 for (i = 0; i < Count; i++)
914 {
915 Status = gBS->HandleProtocol(Handles[i], &gEfiComponentNameProtocolGuid, (VOID **)&NameProtocol);
916 if (EFI_ERROR(Status))
917 {
918 debug();
919 continue;
920 }
921
922 VENTOY_GET_COMPONENT_NAME(NameProtocol, DriverName);
923
924 Status = gBS->HandleProtocol(Handles[i], &gEfiDriverBindingProtocolGuid, (VOID **)&DriverBindProtocol);
925 if (EFI_ERROR(Status))
926 {
927 debug("### 1 No DriverBind <%s> <%r>", DriverName, Status);
928 continue;
929 }
930
931 ventoy_add_filesystem_wrapper(DriverBindProtocol, DriverName);
932 }
933
934 FreePool(Handles);
935
936 return EFI_SUCCESS;
937 }
938
939 STATIC EFI_STATUS EFIAPI ventoy_wrapper_driver_bind_support
940 (
941 IN EFI_DRIVER_BINDING_PROTOCOL *This,
942 IN EFI_HANDLE ControllerHandle,
943 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
944 )
945 {
946 UINTN i;
947 EFI_STATUS Status = EFI_SUCCESS;
948 EFI_DEVICE_PATH_PROTOCOL *DevicePath = NULL;
949 EFI_DRIVER_BINDING_SUPPORTED pfOldSupport = NULL;
950
951 for (i = 0; i < g_DriverBindWrapperCnt; i++)
952 {
953 if (g_DriverBindWrapperList[i].DriverBinding == This)
954 {
955 pfOldSupport = g_DriverBindWrapperList[i].pfOldSupport;
956 break;
957 }
958 }
959
960 debug("ventoy_wrapper_driver_bind_support %lu %p", i, pfOldSupport);
961
962 if (!pfOldSupport)
963 {
964 return EFI_UNSUPPORTED;
965 }
966
967 Status = gBS->HandleProtocol(ControllerHandle, &gEfiDevicePathProtocolGuid, (VOID **)&DevicePath);
968 if (EFI_ERROR(Status))
969 {
970 goto out;
971 }
972
973 if (0 == CompareMem(gBlockData.Path, DevicePath, gBlockData.DevicePathCompareLen))
974 {
975 debug("return EFI_UNSUPPORTED for ventoy");
976 return EFI_UNSUPPORTED;
977 }
978
979 out:
980 return pfOldSupport(This, ControllerHandle, RemainingDevicePath);
981 }
982
983 EFI_STATUS ventoy_disable_ex_filesystem(VOID)
984 {
985 UINTN i;
986
987 ventoy_find_filesystem_driverbind();
988
989 for (i = 0; i < g_DriverBindWrapperCnt; i++)
990 {
991 g_DriverBindWrapperList[i].DriverBinding->Supported = ventoy_wrapper_driver_bind_support;
992 }
993
994 debug("Wrapper Ex Driver Binding %lu", g_DriverBindWrapperCnt);
995 ventoy_debug_pause();
996
997 return EFI_SUCCESS;
998 }
999
1000 EFI_STATUS ventoy_enable_ex_filesystem(VOID)
1001 {
1002 UINTN i;
1003
1004 for (i = 0; i < g_DriverBindWrapperCnt; i++)
1005 {
1006 g_DriverBindWrapperList[i].DriverBinding->Supported = g_DriverBindWrapperList[i].pfOldSupport;
1007 }
1008 g_DriverBindWrapperCnt = 0;
1009
1010 return EFI_SUCCESS;
1011 }
1012
1013 EFI_STATUS EFIAPI ventoy_block_io_read_512
1014 (
1015 IN EFI_BLOCK_IO_PROTOCOL *This,
1016 IN UINT32 MediaId,
1017 IN EFI_LBA Lba,
1018 IN UINTN BufferSize,
1019 OUT VOID *Buffer
1020 )
1021 {
1022 EFI_LBA Mod;
1023 UINTN ReadSize;
1024 UINT8 *CurBuf = NULL;
1025 EFI_STATUS Status = EFI_SUCCESS;
1026
1027 debug("ventoy_block_io_read_512 %lu %lu Buffer:%p\n", Lba, BufferSize / 512, Buffer);
1028
1029 CurBuf = (UINT8 *)Buffer;
1030
1031 Mod = Lba % 4;
1032 if (Mod > 0)
1033 {
1034 Status |= g_sector_2048_read(This, MediaId, Lba / 4, 2048, g_sector_buf);
1035
1036 if (BufferSize <= (4 - Mod) * 512)
1037 {
1038 CopyMem(CurBuf, g_sector_buf + Mod * 512, BufferSize);
1039 return EFI_SUCCESS;
1040 }
1041 else
1042 {
1043 ReadSize = (4 - Mod) * 512;
1044 CopyMem(CurBuf, g_sector_buf + Mod * 512, ReadSize);
1045 CurBuf += ReadSize;
1046 Lba += (4 - Mod);
1047 BufferSize -= ReadSize;
1048 }
1049 }
1050
1051 if (BufferSize >= 2048)
1052 {
1053 ReadSize = BufferSize / 2048 * 2048;
1054
1055 Status |= g_sector_2048_read(This, MediaId, Lba / 4, ReadSize, CurBuf);
1056 CurBuf += ReadSize;
1057
1058 Lba += ReadSize / 512;
1059 BufferSize -= ReadSize;
1060 }
1061
1062 if (BufferSize > 0)
1063 {
1064 Status |= g_sector_2048_read(This, MediaId, Lba / 4, 2048, g_sector_buf);
1065 CopyMem(CurBuf, g_sector_buf, BufferSize);
1066 }
1067
1068 return Status;
1069 }
1070
1071 EFI_STATUS EFIAPI ventoy_block_io_write_512
1072 (
1073 IN EFI_BLOCK_IO_PROTOCOL *This,
1074 IN UINT32 MediaId,
1075 IN EFI_LBA Lba,
1076 IN UINTN BufferSize,
1077 IN VOID *Buffer
1078 )
1079 {
1080 EFI_LBA Mod;
1081 UINTN ReadSize;
1082 UINT8 *CurBuf = NULL;
1083 EFI_STATUS Status = EFI_SUCCESS;
1084
1085 debug("ventoy_block_io_write_512 %lu %lu\n", Lba, BufferSize / 512);
1086
1087 CurBuf = (UINT8 *)Buffer;
1088
1089 Mod = Lba % 4;
1090 if (Mod > 0)
1091 {
1092 Status |= g_sector_2048_read(This, MediaId, Lba / 4, 2048, g_sector_buf);
1093
1094 if (BufferSize <= (4 - Mod) * 512)
1095 {
1096 CopyMem(g_sector_buf + Mod * 512, CurBuf, BufferSize);
1097 return g_sector_2048_write(This, MediaId, Lba / 4, 2048, g_sector_buf);
1098 }
1099 else
1100 {
1101 ReadSize = (4 - Mod) * 512;
1102 CopyMem(g_sector_buf + Mod * 512, CurBuf, ReadSize);
1103 g_sector_2048_write(This, MediaId, Lba / 4, 2048, g_sector_buf);
1104
1105 CurBuf += ReadSize;
1106 Lba += (4 - Mod);
1107 BufferSize -= ReadSize;
1108 }
1109 }
1110
1111 if (BufferSize >= 2048)
1112 {
1113 ReadSize = BufferSize / 2048 * 2048;
1114
1115 Status |= g_sector_2048_write(This, MediaId, Lba / 4, ReadSize, CurBuf);
1116 CurBuf += ReadSize;
1117
1118 Lba += ReadSize / 512;
1119 BufferSize -= ReadSize;
1120 }
1121
1122 if (BufferSize > 0)
1123 {
1124 Status |= g_sector_2048_read(This, MediaId, Lba / 4, 2048, g_sector_buf);
1125
1126 CopyMem(g_sector_buf, CurBuf, BufferSize);
1127 g_sector_2048_write(This, MediaId, Lba / 4, 2048, g_sector_buf);
1128 }
1129
1130 return Status;
1131 }
1132
1133 EFI_STATUS EFIAPI ventoy_install_blockio(IN EFI_HANDLE ImageHandle, IN UINT64 ImgSize)
1134 {
1135 EFI_STATUS Status = EFI_SUCCESS;
1136 EFI_BLOCK_IO_PROTOCOL *pBlockIo = &(gBlockData.BlockIo);
1137
1138 ventoy_fill_device_path();
1139
1140 debug("install block io protocol %p", ImageHandle);
1141 ventoy_debug_pause();
1142
1143 if (gSector512Mode)
1144 {
1145 gBlockData.Media.BlockSize = 512;
1146 gBlockData.Media.LastBlock = ImgSize / 512 - 1;
1147 }
1148 else
1149 {
1150 gBlockData.Media.BlockSize = 2048;
1151 gBlockData.Media.LastBlock = ImgSize / 2048 - 1;
1152 }
1153
1154 gBlockData.Media.ReadOnly = TRUE;
1155 gBlockData.Media.MediaPresent = 1;
1156 gBlockData.Media.LogicalBlocksPerPhysicalBlock = 1;
1157
1158 pBlockIo->Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3;
1159 pBlockIo->Media = &(gBlockData.Media);
1160 pBlockIo->Reset = ventoy_block_io_reset;
1161
1162 if (gSector512Mode)
1163 {
1164 g_sector_2048_read = gMemdiskMode ? ventoy_block_io_ramdisk_read : ventoy_block_io_read;
1165 g_sector_2048_write = gMemdiskMode ? ventoy_block_io_ramdisk_write : ventoy_block_io_write;
1166 pBlockIo->ReadBlocks = ventoy_block_io_read_512;
1167 pBlockIo->WriteBlocks = ventoy_block_io_write_512;
1168 }
1169 else
1170 {
1171 pBlockIo->ReadBlocks = gMemdiskMode ? ventoy_block_io_ramdisk_read : ventoy_block_io_read;
1172 pBlockIo->WriteBlocks = ventoy_block_io_write;
1173 }
1174
1175 pBlockIo->FlushBlocks = ventoy_block_io_flush;
1176
1177 Status = gBS->InstallMultipleProtocolInterfaces(&gBlockData.Handle,
1178 &gEfiBlockIoProtocolGuid, &gBlockData.BlockIo,
1179 &gEfiDevicePathProtocolGuid, gBlockData.Path,
1180 NULL);
1181 debug("Install protocol %r %p", Status, gBlockData.Handle);
1182 if (EFI_ERROR(Status))
1183 {
1184 return Status;
1185 }
1186
1187 Status = ventoy_connect_driver(gBlockData.Handle, L"Disk I/O Driver");
1188 debug("Connect disk IO driver %r", Status);
1189
1190 Status = ventoy_connect_driver(gBlockData.Handle, L"Partition Driver");
1191 debug("Connect partition driver %r", Status);
1192 if (EFI_ERROR(Status))
1193 {
1194 Status = gBS->ConnectController(gBlockData.Handle, NULL, NULL, TRUE);
1195 debug("Connect all controller %r", Status);
1196 }
1197
1198 ventoy_debug_pause();
1199
1200 return EFI_SUCCESS;
1201 }
1202
1203 #if 0
1204 /* For file replace */
1205 #endif
1206
1207 STATIC EFI_STATUS EFIAPI
1208 ventoy_wrapper_fs_open(EFI_FILE_HANDLE This, EFI_FILE_HANDLE *New, CHAR16 *Name, UINT64 Mode, UINT64 Attributes)
1209 {
1210 (VOID)This;
1211 (VOID)New;
1212 (VOID)Name;
1213 (VOID)Mode;
1214 (VOID)Attributes;
1215 return EFI_SUCCESS;
1216 }
1217
1218 STATIC EFI_STATUS EFIAPI
1219 ventoy_wrapper_file_open_ex(EFI_FILE_HANDLE This, EFI_FILE_HANDLE *New, CHAR16 *Name, UINT64 Mode, UINT64 Attributes, EFI_FILE_IO_TOKEN *Token)
1220 {
1221 return ventoy_wrapper_fs_open(This, New, Name, Mode, Attributes);
1222 }
1223
1224 STATIC EFI_STATUS EFIAPI
1225 ventoy_wrapper_file_delete(EFI_FILE_HANDLE This)
1226 {
1227 (VOID)This;
1228 return EFI_SUCCESS;
1229 }
1230
1231 STATIC EFI_STATUS EFIAPI
1232 ventoy_wrapper_file_set_info(EFI_FILE_HANDLE This, EFI_GUID *Type, UINTN Len, VOID *Data)
1233 {
1234 return EFI_SUCCESS;
1235 }
1236
1237 STATIC EFI_STATUS EFIAPI
1238 ventoy_wrapper_file_flush(EFI_FILE_HANDLE This)
1239 {
1240 (VOID)This;
1241 return EFI_SUCCESS;
1242 }
1243
1244 /* Ex version */
1245 STATIC EFI_STATUS EFIAPI
1246 ventoy_wrapper_file_flush_ex(EFI_FILE_HANDLE This, EFI_FILE_IO_TOKEN *Token)
1247 {
1248 (VOID)This;
1249 (VOID)Token;
1250 return EFI_SUCCESS;
1251 }
1252
1253
1254 STATIC EFI_STATUS EFIAPI
1255 ventoy_wrapper_file_write(EFI_FILE_HANDLE This, UINTN *Len, VOID *Data)
1256 {
1257 (VOID)This;
1258 (VOID)Len;
1259 (VOID)Data;
1260
1261 return EFI_WRITE_PROTECTED;
1262 }
1263
1264 STATIC EFI_STATUS EFIAPI
1265 ventoy_wrapper_file_write_ex(IN EFI_FILE_PROTOCOL *This, IN OUT EFI_FILE_IO_TOKEN *Token)
1266 {
1267 return ventoy_wrapper_file_write(This, &(Token->BufferSize), Token->Buffer);
1268 }
1269
1270
1271 STATIC EFI_STATUS EFIAPI
1272 ventoy_wrapper_file_close(EFI_FILE_HANDLE This)
1273 {
1274 (VOID)This;
1275 return EFI_SUCCESS;
1276 }
1277
1278
1279 STATIC EFI_STATUS EFIAPI
1280 ventoy_wrapper_file_set_pos(EFI_FILE_HANDLE This, UINT64 Position)
1281 {
1282 (VOID)This;
1283
1284 if (Position <= g_efi_file_replace.FileSizeBytes)
1285 {
1286 g_efi_file_replace.CurPos = Position;
1287 }
1288 else
1289 {
1290 g_efi_file_replace.CurPos = g_efi_file_replace.FileSizeBytes;
1291 }
1292
1293 return EFI_SUCCESS;
1294 }
1295
1296 STATIC EFI_STATUS EFIAPI
1297 ventoy_wrapper_file_get_pos(EFI_FILE_HANDLE This, UINT64 *Position)
1298 {
1299 (VOID)This;
1300
1301 *Position = g_efi_file_replace.CurPos;
1302
1303 return EFI_SUCCESS;
1304 }
1305
1306
1307 STATIC EFI_STATUS EFIAPI
1308 ventoy_wrapper_file_get_info(EFI_FILE_HANDLE This, EFI_GUID *Type, UINTN *Len, VOID *Data)
1309 {
1310 EFI_FILE_INFO *Info = (EFI_FILE_INFO *) Data;
1311
1312 debug("ventoy_wrapper_file_get_info ... %u", *Len);
1313
1314 if (!CompareGuid(Type, &gEfiFileInfoGuid))
1315 {
1316 return EFI_INVALID_PARAMETER;
1317 }
1318
1319 if (*Len == 0)
1320 {
1321 *Len = 384;
1322 return EFI_BUFFER_TOO_SMALL;
1323 }
1324
1325 ZeroMem(Data, sizeof(EFI_FILE_INFO));
1326
1327 Info->Size = sizeof(EFI_FILE_INFO);
1328 Info->FileSize = g_efi_file_replace.FileSizeBytes;
1329 Info->PhysicalSize = g_efi_file_replace.FileSizeBytes;
1330 Info->Attribute = EFI_FILE_READ_ONLY;
1331 //Info->FileName = EFI_FILE_READ_ONLY;
1332
1333 *Len = Info->Size;
1334
1335 return EFI_SUCCESS;
1336 }
1337
1338 STATIC EFI_STATUS EFIAPI
1339 ventoy_wrapper_file_read(EFI_FILE_HANDLE This, UINTN *Len, VOID *Data)
1340 {
1341 EFI_LBA Lba;
1342 UINTN ReadLen = *Len;
1343
1344 (VOID)This;
1345
1346 debug("ventoy_wrapper_file_read ... %u", *Len);
1347
1348 if (g_efi_file_replace.CurPos + ReadLen > g_efi_file_replace.FileSizeBytes)
1349 {
1350 ReadLen = g_efi_file_replace.FileSizeBytes - g_efi_file_replace.CurPos;
1351 }
1352
1353 Lba = g_efi_file_replace.CurPos / 2048 + g_efi_file_replace.BlockIoSectorStart;
1354
1355 ventoy_block_io_read(NULL, 0, Lba, ReadLen, Data);
1356
1357 *Len = ReadLen;
1358
1359 g_efi_file_replace.CurPos += ReadLen;
1360
1361 return EFI_SUCCESS;
1362 }
1363
1364 STATIC EFI_STATUS EFIAPI
1365 ventoy_wrapper_file_read_ex(IN EFI_FILE_PROTOCOL *This, IN OUT EFI_FILE_IO_TOKEN *Token)
1366 {
1367 return ventoy_wrapper_file_read(This, &(Token->BufferSize), Token->Buffer);
1368 }
1369
1370 STATIC EFI_STATUS EFIAPI ventoy_wrapper_file_procotol(EFI_FILE_PROTOCOL *File)
1371 {
1372 File->Revision = EFI_FILE_PROTOCOL_REVISION2;
1373 File->Open = ventoy_wrapper_fs_open;
1374 File->Close = ventoy_wrapper_file_close;
1375 File->Delete = ventoy_wrapper_file_delete;
1376 File->Read = ventoy_wrapper_file_read;
1377 File->Write = ventoy_wrapper_file_write;
1378 File->GetPosition = ventoy_wrapper_file_get_pos;
1379 File->SetPosition = ventoy_wrapper_file_set_pos;
1380 File->GetInfo = ventoy_wrapper_file_get_info;
1381 File->SetInfo = ventoy_wrapper_file_set_info;
1382 File->Flush = ventoy_wrapper_file_flush;
1383 File->OpenEx = ventoy_wrapper_file_open_ex;
1384 File->ReadEx = ventoy_wrapper_file_read_ex;
1385 File->WriteEx = ventoy_wrapper_file_write_ex;
1386 File->FlushEx = ventoy_wrapper_file_flush_ex;
1387
1388 return EFI_SUCCESS;
1389 }
1390
1391 STATIC EFI_STATUS EFIAPI ventoy_wrapper_file_open
1392 (
1393 EFI_FILE_HANDLE This,
1394 EFI_FILE_HANDLE *New,
1395 CHAR16 *Name,
1396 UINT64 Mode,
1397 UINT64 Attributes
1398 )
1399 {
1400 UINT32 i = 0;
1401 UINT32 j = 0;
1402 UINT64 Sectors = 0;
1403 EFI_STATUS Status = EFI_SUCCESS;
1404 CHAR8 TmpName[256];
1405 ventoy_virt_chunk *virt = NULL;
1406
1407 debug("## ventoy_wrapper_file_open <%s> ", Name);
1408
1409 Status = g_original_fopen(This, New, Name, Mode, Attributes);
1410 if (EFI_ERROR(Status))
1411 {
1412 return Status;
1413 }
1414
1415 if (g_file_replace_list && g_file_replace_list->magic == GRUB_FILE_REPLACE_MAGIC &&
1416 g_file_replace_list->new_file_virtual_id < g_virt_chunk_num)
1417 {
1418 AsciiSPrint(TmpName, sizeof(TmpName), "%s", Name);
1419 for (j = 0; j < 4; j++)
1420 {
1421 if (0 == AsciiStrCmp(g_file_replace_list[i].old_file_name[j], TmpName))
1422 {
1423 g_original_fclose(*New);
1424 *New = &g_efi_file_replace.WrapperHandle;
1425 ventoy_wrapper_file_procotol(*New);
1426
1427 virt = g_virt_chunk + g_file_replace_list->new_file_virtual_id;
1428
1429 Sectors = (virt->mem_sector_end - virt->mem_sector_start) + (virt->remap_sector_end - virt->remap_sector_start);
1430
1431 g_efi_file_replace.BlockIoSectorStart = virt->mem_sector_start;
1432 g_efi_file_replace.FileSizeBytes = Sectors * 2048;
1433
1434 if (gDebugPrint)
1435 {
1436 debug("## ventoy_wrapper_file_open <%s> BlockStart:%lu Sectors:%lu Bytes:%lu", Name,
1437 g_efi_file_replace.BlockIoSectorStart, Sectors, Sectors * 2048);
1438 sleep(3);
1439 }
1440
1441 return Status;
1442 }
1443 }
1444
1445 if (StrCmp(Name, L"\\EFI\\BOOT") == 0)
1446 {
1447 (*New)->Open = ventoy_wrapper_file_open;
1448 }
1449 }
1450
1451 return Status;
1452 }
1453
1454 EFI_STATUS EFIAPI ventoy_wrapper_open_volume
1455 (
1456 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
1457 OUT EFI_FILE_PROTOCOL **Root
1458 )
1459 {
1460 EFI_STATUS Status = EFI_SUCCESS;
1461
1462 Status = g_original_open_volume(This, Root);
1463 if (!EFI_ERROR(Status))
1464 {
1465 g_original_fopen = (*Root)->Open;
1466 g_original_fclose = (*Root)->Close;
1467 (*Root)->Open = ventoy_wrapper_file_open;
1468 }
1469
1470 return Status;
1471 }
1472
1473 EFI_STATUS EFIAPI ventoy_wrapper_push_openvolume(IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME OpenVolume)
1474 {
1475 g_original_open_volume = OpenVolume;
1476 return EFI_SUCCESS;
1477 }
1478
1479 #if 0
1480 /* For auto skip Windows 'Press any key to boot from CD or DVD ...' */
1481 #endif
1482
1483 STATIC EFI_STATUS EFIAPI ventoy_wrapper_read_key_ex
1484 (
1485 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
1486 OUT EFI_KEY_DATA *KeyData
1487 )
1488 {
1489 /* only hook once before BCD file read */
1490 if (g_keyboard_hook_count == 0 && g_blockio_bcd_read_done == FALSE)
1491 {
1492 g_keyboard_hook_count++;
1493
1494 KeyData->Key.ScanCode = SCAN_DELETE;
1495 KeyData->Key.UnicodeChar = 0;
1496 KeyData->KeyState.KeyShiftState = 0;
1497 KeyData->KeyState.KeyToggleState = 0;
1498
1499 return EFI_SUCCESS;
1500 }
1501
1502 return g_org_read_key_ex(This, KeyData);
1503 }
1504
1505 EFI_STATUS EFIAPI ventoy_wrapper_read_key
1506 (
1507 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
1508 OUT EFI_INPUT_KEY *Key
1509 )
1510 {
1511 /* only hook once before BCD file read */
1512 if (g_keyboard_hook_count == 0 && g_blockio_bcd_read_done == FALSE)
1513 {
1514 g_keyboard_hook_count++;
1515
1516 Key->ScanCode = SCAN_DELETE;
1517 Key->UnicodeChar = 0;
1518 return EFI_SUCCESS;
1519 }
1520
1521 return g_org_read_key(This, Key);
1522 }
1523
1524 EFI_STATUS ventoy_hook_keyboard_start(VOID)
1525 {
1526 g_blockio_start_record_bcd = TRUE;
1527 g_blockio_bcd_read_done = FALSE;
1528 g_keyboard_hook_count = 0;
1529
1530 if (g_con_simple_input_ex)
1531 {
1532 g_org_read_key_ex = g_con_simple_input_ex->ReadKeyStrokeEx;
1533 g_con_simple_input_ex->ReadKeyStrokeEx = ventoy_wrapper_read_key_ex;
1534 }
1535
1536 g_org_read_key = gST->ConIn->ReadKeyStroke;
1537 gST->ConIn->ReadKeyStroke = ventoy_wrapper_read_key;
1538
1539 return EFI_SUCCESS;
1540 }
1541
1542 EFI_STATUS ventoy_hook_keyboard_stop(VOID)
1543 {
1544 g_blockio_start_record_bcd = FALSE;
1545 g_blockio_bcd_read_done = FALSE;
1546 g_keyboard_hook_count = 0;
1547
1548 if (g_con_simple_input_ex)
1549 {
1550 g_con_simple_input_ex->ReadKeyStrokeEx = g_org_read_key_ex;
1551 }
1552
1553 gST->ConIn->ReadKeyStroke = g_org_read_key;
1554
1555 return EFI_SUCCESS;
1556 }
1557
1558 #if 0
1559 /* Fixup the 1st cdrom influnce for Windows boot */
1560 #endif
1561
1562 STATIC EFI_STATUS EFIAPI ventoy_wrapper_locate_handle
1563 (
1564 IN EFI_LOCATE_SEARCH_TYPE SearchType,
1565 IN EFI_GUID *Protocol, OPTIONAL
1566 IN VOID *SearchKey, OPTIONAL
1567 IN OUT UINTN *BufferSize,
1568 OUT EFI_HANDLE *Buffer
1569 )
1570 {
1571 UINTN i;
1572 EFI_HANDLE Handle = NULL;
1573 EFI_STATUS Status = EFI_SUCCESS;
1574
1575 Status = g_org_locate_handle(SearchType, Protocol, SearchKey, BufferSize, Buffer);
1576
1577 if (EFI_SUCCESS == Status && Protocol && CompareGuid(&gEfiBlockIoProtocolGuid, Protocol))
1578 {
1579 for (i = 0; i < (*BufferSize) / sizeof(EFI_HANDLE); i++)
1580 {
1581 if (Buffer[i] == gBlockData.Handle)
1582 {
1583 Handle = Buffer[0];
1584 Buffer[0] = Buffer[i];
1585 Buffer[i] = Handle;
1586 break;
1587 }
1588 }
1589 }
1590
1591 return Status;
1592 }
1593
1594 EFI_STATUS ventoy_hook_1st_cdrom_start(VOID)
1595 {
1596 g_org_locate_handle = gBS->LocateHandle;
1597 gBS->LocateHandle = ventoy_wrapper_locate_handle;
1598
1599 return EFI_SUCCESS;
1600 }
1601
1602 EFI_STATUS ventoy_hook_1st_cdrom_stop(VOID)
1603 {
1604 gBS->LocateHandle = g_org_locate_handle;
1605 g_org_locate_handle = NULL;
1606
1607 return EFI_SUCCESS;
1608 }
1609