]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/VentoyProtocol.c
Continue to boot even the ISO file size is invalid.
[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 gBlockData.Media.ReadOnly = FALSE;
1142 }
1143 else
1144 {
1145 gBlockData.Media.BlockSize = 2048;
1146 gBlockData.Media.LastBlock = ImgSize / 2048 - 1;
1147 gBlockData.Media.ReadOnly = TRUE;
1148 }
1149
1150 gBlockData.Media.MediaPresent = 1;
1151 gBlockData.Media.LogicalBlocksPerPhysicalBlock = 1;
1152
1153 pBlockIo->Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3;
1154 pBlockIo->Media = &(gBlockData.Media);
1155 pBlockIo->Reset = ventoy_block_io_reset;
1156
1157 if (gSector512Mode)
1158 {
1159 g_sector_2048_read = gMemdiskMode ? ventoy_block_io_ramdisk_read : ventoy_block_io_read;
1160 g_sector_2048_write = gMemdiskMode ? ventoy_block_io_ramdisk_write : ventoy_block_io_write;
1161 pBlockIo->ReadBlocks = ventoy_block_io_read_512;
1162 pBlockIo->WriteBlocks = ventoy_block_io_write_512;
1163 }
1164 else
1165 {
1166 pBlockIo->ReadBlocks = gMemdiskMode ? ventoy_block_io_ramdisk_read : ventoy_block_io_read;
1167 pBlockIo->WriteBlocks = ventoy_block_io_write;
1168 }
1169
1170 pBlockIo->FlushBlocks = ventoy_block_io_flush;
1171
1172 Status = gBS->InstallMultipleProtocolInterfaces(&gBlockData.Handle,
1173 &gEfiBlockIoProtocolGuid, &gBlockData.BlockIo,
1174 &gEfiDevicePathProtocolGuid, gBlockData.Path,
1175 NULL);
1176 debug("Install protocol %r %p", Status, gBlockData.Handle);
1177 if (EFI_ERROR(Status))
1178 {
1179 return Status;
1180 }
1181
1182 Status = ventoy_connect_driver(gBlockData.Handle, L"Disk I/O Driver");
1183 debug("Connect disk IO driver %r", Status);
1184
1185 Status = ventoy_connect_driver(gBlockData.Handle, L"Partition Driver");
1186 debug("Connect partition driver %r", Status);
1187 if (EFI_ERROR(Status))
1188 {
1189 Status = gBS->ConnectController(gBlockData.Handle, NULL, NULL, TRUE);
1190 debug("Connect all controller %r", Status);
1191 }
1192
1193 ventoy_debug_pause();
1194
1195 return EFI_SUCCESS;
1196 }
1197
1198 #if 0
1199 /* For file replace */
1200 #endif
1201
1202 STATIC EFI_STATUS EFIAPI
1203 ventoy_wrapper_fs_open(EFI_FILE_HANDLE This, EFI_FILE_HANDLE *New, CHAR16 *Name, UINT64 Mode, UINT64 Attributes)
1204 {
1205 (VOID)This;
1206 (VOID)New;
1207 (VOID)Name;
1208 (VOID)Mode;
1209 (VOID)Attributes;
1210 return EFI_SUCCESS;
1211 }
1212
1213 STATIC EFI_STATUS EFIAPI
1214 ventoy_wrapper_file_open_ex(EFI_FILE_HANDLE This, EFI_FILE_HANDLE *New, CHAR16 *Name, UINT64 Mode, UINT64 Attributes, EFI_FILE_IO_TOKEN *Token)
1215 {
1216 return ventoy_wrapper_fs_open(This, New, Name, Mode, Attributes);
1217 }
1218
1219 STATIC EFI_STATUS EFIAPI
1220 ventoy_wrapper_file_delete(EFI_FILE_HANDLE This)
1221 {
1222 (VOID)This;
1223 return EFI_SUCCESS;
1224 }
1225
1226 STATIC EFI_STATUS EFIAPI
1227 ventoy_wrapper_file_set_info(EFI_FILE_HANDLE This, EFI_GUID *Type, UINTN Len, VOID *Data)
1228 {
1229 return EFI_SUCCESS;
1230 }
1231
1232 STATIC EFI_STATUS EFIAPI
1233 ventoy_wrapper_file_flush(EFI_FILE_HANDLE This)
1234 {
1235 (VOID)This;
1236 return EFI_SUCCESS;
1237 }
1238
1239 /* Ex version */
1240 STATIC EFI_STATUS EFIAPI
1241 ventoy_wrapper_file_flush_ex(EFI_FILE_HANDLE This, EFI_FILE_IO_TOKEN *Token)
1242 {
1243 (VOID)This;
1244 (VOID)Token;
1245 return EFI_SUCCESS;
1246 }
1247
1248
1249 STATIC EFI_STATUS EFIAPI
1250 ventoy_wrapper_file_write(EFI_FILE_HANDLE This, UINTN *Len, VOID *Data)
1251 {
1252 (VOID)This;
1253 (VOID)Len;
1254 (VOID)Data;
1255
1256 return EFI_WRITE_PROTECTED;
1257 }
1258
1259 STATIC EFI_STATUS EFIAPI
1260 ventoy_wrapper_file_write_ex(IN EFI_FILE_PROTOCOL *This, IN OUT EFI_FILE_IO_TOKEN *Token)
1261 {
1262 return ventoy_wrapper_file_write(This, &(Token->BufferSize), Token->Buffer);
1263 }
1264
1265
1266 STATIC EFI_STATUS EFIAPI
1267 ventoy_wrapper_file_close(EFI_FILE_HANDLE This)
1268 {
1269 (VOID)This;
1270 return EFI_SUCCESS;
1271 }
1272
1273
1274 STATIC EFI_STATUS EFIAPI
1275 ventoy_wrapper_file_set_pos(EFI_FILE_HANDLE This, UINT64 Position)
1276 {
1277 (VOID)This;
1278
1279 if (Position <= g_efi_file_replace.FileSizeBytes)
1280 {
1281 g_efi_file_replace.CurPos = Position;
1282 }
1283 else
1284 {
1285 g_efi_file_replace.CurPos = g_efi_file_replace.FileSizeBytes;
1286 }
1287
1288 return EFI_SUCCESS;
1289 }
1290
1291 STATIC EFI_STATUS EFIAPI
1292 ventoy_wrapper_file_get_pos(EFI_FILE_HANDLE This, UINT64 *Position)
1293 {
1294 (VOID)This;
1295
1296 *Position = g_efi_file_replace.CurPos;
1297
1298 return EFI_SUCCESS;
1299 }
1300
1301
1302 STATIC EFI_STATUS EFIAPI
1303 ventoy_wrapper_file_get_info(EFI_FILE_HANDLE This, EFI_GUID *Type, UINTN *Len, VOID *Data)
1304 {
1305 EFI_FILE_INFO *Info = (EFI_FILE_INFO *) Data;
1306
1307 debug("ventoy_wrapper_file_get_info ... %u", *Len);
1308
1309 if (!CompareGuid(Type, &gEfiFileInfoGuid))
1310 {
1311 return EFI_INVALID_PARAMETER;
1312 }
1313
1314 if (*Len == 0)
1315 {
1316 *Len = 384;
1317 return EFI_BUFFER_TOO_SMALL;
1318 }
1319
1320 ZeroMem(Data, sizeof(EFI_FILE_INFO));
1321
1322 Info->Size = sizeof(EFI_FILE_INFO);
1323 Info->FileSize = g_efi_file_replace.FileSizeBytes;
1324 Info->PhysicalSize = g_efi_file_replace.FileSizeBytes;
1325 Info->Attribute = EFI_FILE_READ_ONLY;
1326 //Info->FileName = EFI_FILE_READ_ONLY;
1327
1328 *Len = Info->Size;
1329
1330 return EFI_SUCCESS;
1331 }
1332
1333 STATIC EFI_STATUS EFIAPI
1334 ventoy_wrapper_file_read(EFI_FILE_HANDLE This, UINTN *Len, VOID *Data)
1335 {
1336 EFI_LBA Lba;
1337 UINTN ReadLen = *Len;
1338
1339 (VOID)This;
1340
1341 debug("ventoy_wrapper_file_read ... %u", *Len);
1342
1343 if (g_efi_file_replace.CurPos + ReadLen > g_efi_file_replace.FileSizeBytes)
1344 {
1345 ReadLen = g_efi_file_replace.FileSizeBytes - g_efi_file_replace.CurPos;
1346 }
1347
1348 Lba = g_efi_file_replace.CurPos / 2048 + g_efi_file_replace.BlockIoSectorStart;
1349
1350 ventoy_block_io_read(NULL, 0, Lba, ReadLen, Data);
1351
1352 *Len = ReadLen;
1353
1354 g_efi_file_replace.CurPos += ReadLen;
1355
1356 return EFI_SUCCESS;
1357 }
1358
1359 STATIC EFI_STATUS EFIAPI
1360 ventoy_wrapper_file_read_ex(IN EFI_FILE_PROTOCOL *This, IN OUT EFI_FILE_IO_TOKEN *Token)
1361 {
1362 return ventoy_wrapper_file_read(This, &(Token->BufferSize), Token->Buffer);
1363 }
1364
1365 STATIC EFI_STATUS EFIAPI ventoy_wrapper_file_procotol(EFI_FILE_PROTOCOL *File)
1366 {
1367 File->Revision = EFI_FILE_PROTOCOL_REVISION2;
1368 File->Open = ventoy_wrapper_fs_open;
1369 File->Close = ventoy_wrapper_file_close;
1370 File->Delete = ventoy_wrapper_file_delete;
1371 File->Read = ventoy_wrapper_file_read;
1372 File->Write = ventoy_wrapper_file_write;
1373 File->GetPosition = ventoy_wrapper_file_get_pos;
1374 File->SetPosition = ventoy_wrapper_file_set_pos;
1375 File->GetInfo = ventoy_wrapper_file_get_info;
1376 File->SetInfo = ventoy_wrapper_file_set_info;
1377 File->Flush = ventoy_wrapper_file_flush;
1378 File->OpenEx = ventoy_wrapper_file_open_ex;
1379 File->ReadEx = ventoy_wrapper_file_read_ex;
1380 File->WriteEx = ventoy_wrapper_file_write_ex;
1381 File->FlushEx = ventoy_wrapper_file_flush_ex;
1382
1383 return EFI_SUCCESS;
1384 }
1385
1386 STATIC EFI_STATUS EFIAPI ventoy_wrapper_file_open
1387 (
1388 EFI_FILE_HANDLE This,
1389 EFI_FILE_HANDLE *New,
1390 CHAR16 *Name,
1391 UINT64 Mode,
1392 UINT64 Attributes
1393 )
1394 {
1395 UINT32 i = 0;
1396 UINT32 j = 0;
1397 UINT64 Sectors = 0;
1398 EFI_STATUS Status = EFI_SUCCESS;
1399 CHAR8 TmpName[256];
1400 ventoy_virt_chunk *virt = NULL;
1401
1402 debug("## ventoy_wrapper_file_open <%s> ", Name);
1403
1404 if ((Mode & EFI_FILE_MODE_WRITE) > 0 && StrCmp(Name, L"\\loader\\random-seed") == 0)
1405 {
1406 if (gDebugPrint)
1407 {
1408 debug("## ventoy_wrapper_file_open return NOT_FOUND for random-seed %lx", Mode);
1409 sleep(3);
1410 }
1411 return EFI_NOT_FOUND;
1412 }
1413
1414 Status = g_original_fopen(This, New, Name, Mode, Attributes);
1415 if (EFI_ERROR(Status))
1416 {
1417 return Status;
1418 }
1419
1420 if (g_file_replace_list && g_file_replace_list->magic == GRUB_FILE_REPLACE_MAGIC &&
1421 g_file_replace_list->new_file_virtual_id < g_virt_chunk_num)
1422 {
1423 AsciiSPrint(TmpName, sizeof(TmpName), "%s", Name);
1424 for (j = 0; j < 4; j++)
1425 {
1426 if (0 == AsciiStrCmp(g_file_replace_list[i].old_file_name[j], TmpName))
1427 {
1428 g_original_fclose(*New);
1429 *New = &g_efi_file_replace.WrapperHandle;
1430 ventoy_wrapper_file_procotol(*New);
1431
1432 virt = g_virt_chunk + g_file_replace_list->new_file_virtual_id;
1433
1434 Sectors = (virt->mem_sector_end - virt->mem_sector_start) + (virt->remap_sector_end - virt->remap_sector_start);
1435
1436 g_efi_file_replace.BlockIoSectorStart = virt->mem_sector_start;
1437 g_efi_file_replace.FileSizeBytes = Sectors * 2048;
1438
1439 if (gDebugPrint)
1440 {
1441 debug("## ventoy_wrapper_file_open <%s> BlockStart:%lu Sectors:%lu Bytes:%lu", Name,
1442 g_efi_file_replace.BlockIoSectorStart, Sectors, Sectors * 2048);
1443 sleep(3);
1444 }
1445
1446 return Status;
1447 }
1448 }
1449
1450 if (StrCmp(Name, L"\\EFI\\BOOT") == 0)
1451 {
1452 (*New)->Open = ventoy_wrapper_file_open;
1453 }
1454 }
1455
1456 return Status;
1457 }
1458
1459 EFI_STATUS EFIAPI ventoy_wrapper_open_volume
1460 (
1461 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
1462 OUT EFI_FILE_PROTOCOL **Root
1463 )
1464 {
1465 EFI_STATUS Status = EFI_SUCCESS;
1466
1467 Status = g_original_open_volume(This, Root);
1468 if (!EFI_ERROR(Status))
1469 {
1470 g_original_fopen = (*Root)->Open;
1471 g_original_fclose = (*Root)->Close;
1472 (*Root)->Open = ventoy_wrapper_file_open;
1473 }
1474
1475 return Status;
1476 }
1477
1478 EFI_STATUS EFIAPI ventoy_wrapper_push_openvolume(IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME OpenVolume)
1479 {
1480 g_original_open_volume = OpenVolume;
1481 return EFI_SUCCESS;
1482 }
1483
1484 #if 0
1485 /* For auto skip Windows 'Press any key to boot from CD or DVD ...' */
1486 #endif
1487
1488 STATIC EFI_STATUS EFIAPI ventoy_wrapper_read_key_ex
1489 (
1490 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
1491 OUT EFI_KEY_DATA *KeyData
1492 )
1493 {
1494 /* only hook once before BCD file read */
1495 if (g_keyboard_hook_count == 0 && g_blockio_bcd_read_done == FALSE)
1496 {
1497 g_keyboard_hook_count++;
1498
1499 KeyData->Key.ScanCode = SCAN_DELETE;
1500 KeyData->Key.UnicodeChar = 0;
1501 KeyData->KeyState.KeyShiftState = 0;
1502 KeyData->KeyState.KeyToggleState = 0;
1503
1504 return EFI_SUCCESS;
1505 }
1506
1507 return g_org_read_key_ex(This, KeyData);
1508 }
1509
1510 EFI_STATUS EFIAPI ventoy_wrapper_read_key
1511 (
1512 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
1513 OUT EFI_INPUT_KEY *Key
1514 )
1515 {
1516 /* only hook once before BCD file read */
1517 if (g_keyboard_hook_count == 0 && g_blockio_bcd_read_done == FALSE)
1518 {
1519 g_keyboard_hook_count++;
1520
1521 Key->ScanCode = SCAN_DELETE;
1522 Key->UnicodeChar = 0;
1523 return EFI_SUCCESS;
1524 }
1525
1526 return g_org_read_key(This, Key);
1527 }
1528
1529 EFI_STATUS ventoy_hook_keyboard_start(VOID)
1530 {
1531 g_blockio_start_record_bcd = TRUE;
1532 g_blockio_bcd_read_done = FALSE;
1533 g_keyboard_hook_count = 0;
1534
1535 if (g_con_simple_input_ex)
1536 {
1537 g_org_read_key_ex = g_con_simple_input_ex->ReadKeyStrokeEx;
1538 g_con_simple_input_ex->ReadKeyStrokeEx = ventoy_wrapper_read_key_ex;
1539 }
1540
1541 g_org_read_key = gST->ConIn->ReadKeyStroke;
1542 gST->ConIn->ReadKeyStroke = ventoy_wrapper_read_key;
1543
1544 return EFI_SUCCESS;
1545 }
1546
1547 EFI_STATUS ventoy_hook_keyboard_stop(VOID)
1548 {
1549 g_blockio_start_record_bcd = FALSE;
1550 g_blockio_bcd_read_done = FALSE;
1551 g_keyboard_hook_count = 0;
1552
1553 if (g_con_simple_input_ex)
1554 {
1555 g_con_simple_input_ex->ReadKeyStrokeEx = g_org_read_key_ex;
1556 }
1557
1558 gST->ConIn->ReadKeyStroke = g_org_read_key;
1559
1560 return EFI_SUCCESS;
1561 }
1562
1563 #if 0
1564 /* Fixup the 1st cdrom influnce for Windows boot */
1565 #endif
1566
1567 STATIC EFI_STATUS EFIAPI ventoy_wrapper_locate_handle
1568 (
1569 IN EFI_LOCATE_SEARCH_TYPE SearchType,
1570 IN EFI_GUID *Protocol, OPTIONAL
1571 IN VOID *SearchKey, OPTIONAL
1572 IN OUT UINTN *BufferSize,
1573 OUT EFI_HANDLE *Buffer
1574 )
1575 {
1576 UINTN i;
1577 EFI_HANDLE Handle = NULL;
1578 EFI_STATUS Status = EFI_SUCCESS;
1579
1580 Status = g_org_locate_handle(SearchType, Protocol, SearchKey, BufferSize, Buffer);
1581
1582 if (EFI_SUCCESS == Status && Protocol && CompareGuid(&gEfiBlockIoProtocolGuid, Protocol))
1583 {
1584 for (i = 0; i < (*BufferSize) / sizeof(EFI_HANDLE); i++)
1585 {
1586 if (Buffer[i] == gBlockData.Handle)
1587 {
1588 Handle = Buffer[0];
1589 Buffer[0] = Buffer[i];
1590 Buffer[i] = Handle;
1591 break;
1592 }
1593 }
1594 }
1595
1596 return Status;
1597 }
1598
1599 EFI_STATUS ventoy_hook_1st_cdrom_start(VOID)
1600 {
1601 g_org_locate_handle = gBS->LocateHandle;
1602 gBS->LocateHandle = ventoy_wrapper_locate_handle;
1603
1604 return EFI_SUCCESS;
1605 }
1606
1607 EFI_STATUS ventoy_hook_1st_cdrom_stop(VOID)
1608 {
1609 gBS->LocateHandle = g_org_locate_handle;
1610 g_org_locate_handle = NULL;
1611
1612 return EFI_SUCCESS;
1613 }
1614