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