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