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