]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/VentoyProtocol.c
prepare for new release
[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 <Ventoy.h>
38
39 UINTN g_iso_buf_size = 0;
40 BOOLEAN gMemdiskMode = FALSE;
41
42 ventoy_sector_flag *g_sector_flag = NULL;
43 UINT32 g_sector_flag_num = 0;
44
45 EFI_FILE_OPEN g_original_fopen = NULL;
46 EFI_FILE_CLOSE g_original_fclose = NULL;
47 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME g_original_open_volume = NULL;
48
49 /* EFI block device vendor device path GUID */
50 EFI_GUID gVtoyBlockDevicePathGuid = VTOY_BLOCK_DEVICE_PATH_GUID;
51
52 #define VENTOY_ISO9660_SECTOR_OVERFLOW 2097152
53
54 BOOLEAN g_fixup_iso9660_secover_enable = FALSE;
55 BOOLEAN g_fixup_iso9660_secover_start = FALSE;
56 UINT64 g_fixup_iso9660_secover_1st_secs = 0;
57 UINT64 g_fixup_iso9660_secover_cur_secs = 0;
58 UINT64 g_fixup_iso9660_secover_tot_secs = 0;
59
60 STATIC UINTN g_keyboard_hook_count = 0;
61 STATIC BOOLEAN g_blockio_start_record_bcd = FALSE;
62 STATIC BOOLEAN g_blockio_bcd_read_done = FALSE;
63
64 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *g_con_simple_input_ex = NULL;
65 STATIC EFI_INPUT_READ_KEY_EX g_org_read_key_ex = NULL;
66 STATIC EFI_INPUT_READ_KEY g_org_read_key = NULL;
67
68 STATIC EFI_LOCATE_HANDLE g_org_locate_handle = NULL;
69
70 BOOLEAN ventoy_is_cdrom_dp_exist(VOID)
71 {
72 UINTN i = 0;
73 UINTN Count = 0;
74 EFI_HANDLE *Handles = NULL;
75 EFI_STATUS Status = EFI_SUCCESS;
76 EFI_DEVICE_PATH_PROTOCOL *DevicePath = NULL;
77
78 Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiDevicePathProtocolGuid,
79 NULL, &Count, &Handles);
80 if (EFI_ERROR(Status))
81 {
82 return FALSE;
83 }
84
85 for (i = 0; i < Count; i++)
86 {
87 Status = gBS->HandleProtocol(Handles[i], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePath);
88 if (EFI_ERROR(Status))
89 {
90 continue;
91 }
92
93 while (!IsDevicePathEnd(DevicePath))
94 {
95 if (MEDIA_DEVICE_PATH == DevicePath->Type && MEDIA_CDROM_DP == DevicePath->SubType)
96 {
97 FreePool(Handles);
98 return TRUE;
99 }
100
101 DevicePath = NextDevicePathNode(DevicePath);
102 }
103 }
104
105 FreePool(Handles);
106 return FALSE;
107 }
108
109 #if 0
110 /* Block IO procotol */
111 #endif
112
113 EFI_STATUS EFIAPI ventoy_block_io_reset
114 (
115 IN EFI_BLOCK_IO_PROTOCOL *This,
116 IN BOOLEAN ExtendedVerification
117 )
118 {
119 (VOID)This;
120 (VOID)ExtendedVerification;
121 return EFI_SUCCESS;
122 }
123
124 STATIC EFI_STATUS EFIAPI ventoy_read_iso_sector
125 (
126 IN UINT64 Sector,
127 IN UINTN Count,
128 OUT VOID *Buffer
129 )
130 {
131 EFI_STATUS Status = EFI_SUCCESS;
132 EFI_LBA MapLba = 0;
133 UINT32 i = 0;
134 UINTN secLeft = 0;
135 UINTN secRead = 0;
136 UINT64 ReadStart = 0;
137 UINT64 ReadEnd = 0;
138 UINT64 OverrideStart = 0;
139 UINT64 OverrideEnd= 0;
140 UINT8 *pCurBuf = (UINT8 *)Buffer;
141 ventoy_img_chunk *pchunk = g_chunk;
142 ventoy_override_chunk *pOverride = g_override_chunk;
143 EFI_BLOCK_IO_PROTOCOL *pRawBlockIo = gBlockData.pRawBlockIo;
144
145 debug("read iso sector %lu count %u", Sector, Count);
146
147 ReadStart = Sector * 2048;
148 ReadEnd = (Sector + Count) * 2048;
149
150 for (i = 0; Count > 0 && i < g_img_chunk_num; i++, pchunk++)
151 {
152 if (Sector >= pchunk->img_start_sector && Sector <= pchunk->img_end_sector)
153 {
154 if (g_chain->disk_sector_size == 512)
155 {
156 MapLba = (Sector - pchunk->img_start_sector) * 4 + pchunk->disk_start_sector;
157 }
158 else
159 {
160 MapLba = (Sector - pchunk->img_start_sector) * 2048 / g_chain->disk_sector_size + pchunk->disk_start_sector;
161 }
162
163 secLeft = pchunk->img_end_sector + 1 - Sector;
164 secRead = (Count < secLeft) ? Count : secLeft;
165
166 Status = pRawBlockIo->ReadBlocks(pRawBlockIo, pRawBlockIo->Media->MediaId,
167 MapLba, secRead * 2048, pCurBuf);
168 if (EFI_ERROR(Status))
169 {
170 debug("Raw disk read block failed %r LBA:%lu Count:%u", Status, MapLba, secRead);
171 return Status;
172 }
173
174 Count -= secRead;
175 Sector += secRead;
176 pCurBuf += secRead * 2048;
177 }
178 }
179
180 if (ReadStart > g_chain->real_img_size_in_bytes)
181 {
182 return EFI_SUCCESS;
183 }
184
185 /* override data */
186 pCurBuf = (UINT8 *)Buffer;
187 for (i = 0; i < g_override_chunk_num; i++, pOverride++)
188 {
189 OverrideStart = pOverride->img_offset;
190 OverrideEnd = pOverride->img_offset + pOverride->override_size;
191
192 if (OverrideStart >= ReadEnd || ReadStart >= OverrideEnd)
193 {
194 continue;
195 }
196
197 if (ReadStart <= OverrideStart)
198 {
199 if (ReadEnd <= OverrideEnd)
200 {
201 CopyMem(pCurBuf + OverrideStart - ReadStart, pOverride->override_data, ReadEnd - OverrideStart);
202 }
203 else
204 {
205 CopyMem(pCurBuf + OverrideStart - ReadStart, pOverride->override_data, pOverride->override_size);
206 }
207 }
208 else
209 {
210 if (ReadEnd <= OverrideEnd)
211 {
212 CopyMem(pCurBuf, pOverride->override_data + ReadStart - OverrideStart, ReadEnd - ReadStart);
213 }
214 else
215 {
216 CopyMem(pCurBuf, pOverride->override_data + ReadStart - OverrideStart, OverrideEnd - ReadStart);
217 }
218 }
219
220 if (g_fixup_iso9660_secover_enable && (!g_fixup_iso9660_secover_start) &&
221 pOverride->override_size == sizeof(ventoy_iso9660_override))
222 {
223 ventoy_iso9660_override *dirent = (ventoy_iso9660_override *)pOverride->override_data;
224 if (dirent->first_sector >= VENTOY_ISO9660_SECTOR_OVERFLOW)
225 {
226 g_fixup_iso9660_secover_start = TRUE;
227 g_fixup_iso9660_secover_cur_secs = 0;
228 }
229 }
230 }
231
232 if (g_blockio_start_record_bcd && FALSE == g_blockio_bcd_read_done)
233 {
234 if (*(UINT32 *)Buffer == 0x66676572)
235 {
236 g_blockio_bcd_read_done = TRUE;
237 }
238 }
239
240 return EFI_SUCCESS;
241 }
242
243 EFI_STATUS EFIAPI ventoy_block_io_ramdisk_read
244 (
245 IN EFI_BLOCK_IO_PROTOCOL *This,
246 IN UINT32 MediaId,
247 IN EFI_LBA Lba,
248 IN UINTN BufferSize,
249 OUT VOID *Buffer
250 )
251 {
252 //debug("### ventoy_block_io_ramdisk_read sector:%u count:%u", (UINT32)Lba, (UINT32)BufferSize / 2048);
253
254 (VOID)This;
255 (VOID)MediaId;
256
257 CopyMem(Buffer, (char *)g_chain + (Lba * 2048), BufferSize);
258
259 if (g_blockio_start_record_bcd && FALSE == g_blockio_bcd_read_done)
260 {
261 if (*(UINT32 *)Buffer == 0x66676572)
262 {
263 g_blockio_bcd_read_done = TRUE;
264 }
265 }
266
267 return EFI_SUCCESS;
268 }
269
270 EFI_LBA EFIAPI ventoy_fixup_iso9660_sector(IN EFI_LBA Lba, UINT32 secNum)
271 {
272 UINT32 i = 0;
273
274 if (g_fixup_iso9660_secover_cur_secs > 0)
275 {
276 Lba += VENTOY_ISO9660_SECTOR_OVERFLOW;
277 g_fixup_iso9660_secover_cur_secs += secNum;
278 if (g_fixup_iso9660_secover_cur_secs >= g_fixup_iso9660_secover_tot_secs)
279 {
280 g_fixup_iso9660_secover_start = FALSE;
281 goto end;
282 }
283 }
284 else
285 {
286 ventoy_iso9660_override *dirent;
287 ventoy_override_chunk *pOverride;
288
289 for (i = 0, pOverride = g_override_chunk; i < g_override_chunk_num; i++, pOverride++)
290 {
291 dirent = (ventoy_iso9660_override *)pOverride->override_data;
292 if (Lba == dirent->first_sector)
293 {
294 g_fixup_iso9660_secover_start = FALSE;
295 goto end;
296 }
297 }
298
299 if (g_fixup_iso9660_secover_start)
300 {
301 for (i = 0, pOverride = g_override_chunk; i < g_override_chunk_num; i++, pOverride++)
302 {
303 dirent = (ventoy_iso9660_override *)pOverride->override_data;
304 if (Lba + VENTOY_ISO9660_SECTOR_OVERFLOW == dirent->first_sector)
305 {
306 g_fixup_iso9660_secover_tot_secs = (dirent->size + 2047) / 2048;
307 g_fixup_iso9660_secover_cur_secs = secNum;
308 if (g_fixup_iso9660_secover_cur_secs >= g_fixup_iso9660_secover_tot_secs)
309 {
310 g_fixup_iso9660_secover_start = FALSE;
311 }
312 Lba += VENTOY_ISO9660_SECTOR_OVERFLOW;
313 goto end;
314 }
315 }
316 }
317 }
318
319 end:
320 return Lba;
321 }
322
323 EFI_STATUS EFIAPI ventoy_block_io_read
324 (
325 IN EFI_BLOCK_IO_PROTOCOL *This,
326 IN UINT32 MediaId,
327 IN EFI_LBA Lba,
328 IN UINTN BufferSize,
329 OUT VOID *Buffer
330 )
331 {
332 UINT32 i = 0;
333 UINT32 j = 0;
334 UINT32 lbacount = 0;
335 UINT32 secNum = 0;
336 UINT64 offset = 0;
337 EFI_LBA curlba = 0;
338 EFI_LBA lastlba = 0;
339 UINT8 *lastbuffer;
340 ventoy_sector_flag *cur_flag;
341 ventoy_virt_chunk *node;
342
343 //debug("### ventoy_block_io_read sector:%u count:%u", (UINT32)Lba, (UINT32)BufferSize / 2048);
344
345 secNum = BufferSize / 2048;
346
347 /* Workaround for SSTR PE loader error */
348 if (g_fixup_iso9660_secover_start)
349 {
350 Lba = ventoy_fixup_iso9660_sector(Lba, secNum);
351 }
352
353 offset = Lba * 2048;
354
355 if (offset + BufferSize <= g_chain->real_img_size_in_bytes)
356 {
357 return ventoy_read_iso_sector(Lba, secNum, Buffer);
358 }
359
360 if (secNum > g_sector_flag_num)
361 {
362 cur_flag = AllocatePool(secNum * sizeof(ventoy_sector_flag));
363 if (NULL == cur_flag)
364 {
365 return EFI_OUT_OF_RESOURCES;
366 }
367
368 FreePool(g_sector_flag);
369 g_sector_flag = cur_flag;
370 g_sector_flag_num = secNum;
371 }
372
373 for (curlba = Lba, cur_flag = g_sector_flag, j = 0; j < secNum; j++, curlba++, cur_flag++)
374 {
375 cur_flag->flag = 0;
376 for (node = g_virt_chunk, i = 0; i < g_virt_chunk_num; i++, node++)
377 {
378 if (curlba >= node->mem_sector_start && curlba < node->mem_sector_end)
379 {
380 CopyMem((UINT8 *)Buffer + j * 2048,
381 (char *)g_virt_chunk + node->mem_sector_offset + (curlba - node->mem_sector_start) * 2048,
382 2048);
383 cur_flag->flag = 1;
384 break;
385 }
386 else if (curlba >= node->remap_sector_start && curlba < node->remap_sector_end)
387 {
388 cur_flag->remap_lba = node->org_sector_start + curlba - node->remap_sector_start;
389 cur_flag->flag = 2;
390 break;
391 }
392 }
393 }
394
395 for (curlba = Lba, cur_flag = g_sector_flag, j = 0; j < secNum; j++, curlba++, cur_flag++)
396 {
397 if (cur_flag->flag == 2)
398 {
399 if (lastlba == 0)
400 {
401 lastbuffer = (UINT8 *)Buffer + j * 2048;
402 lastlba = cur_flag->remap_lba;
403 lbacount = 1;
404 }
405 else if (lastlba + lbacount == cur_flag->remap_lba)
406 {
407 lbacount++;
408 }
409 else
410 {
411 ventoy_read_iso_sector(lastlba, lbacount, lastbuffer);
412 lastbuffer = (UINT8 *)Buffer + j * 2048;
413 lastlba = cur_flag->remap_lba;
414 lbacount = 1;
415 }
416 }
417 }
418
419 if (lbacount > 0)
420 {
421 ventoy_read_iso_sector(lastlba, lbacount, lastbuffer);
422 }
423
424 return EFI_SUCCESS;
425 }
426
427 EFI_STATUS EFIAPI ventoy_block_io_write
428 (
429 IN EFI_BLOCK_IO_PROTOCOL *This,
430 IN UINT32 MediaId,
431 IN EFI_LBA Lba,
432 IN UINTN BufferSize,
433 IN VOID *Buffer
434 )
435 {
436 (VOID)This;
437 (VOID)MediaId;
438 (VOID)Lba;
439 (VOID)BufferSize;
440 (VOID)Buffer;
441 return EFI_WRITE_PROTECTED;
442 }
443
444 EFI_STATUS EFIAPI ventoy_block_io_flush(IN EFI_BLOCK_IO_PROTOCOL *This)
445 {
446 (VOID)This;
447 return EFI_SUCCESS;
448 }
449
450
451 EFI_STATUS EFIAPI ventoy_fill_device_path(VOID)
452 {
453 UINTN NameLen = 0;
454 UINT8 TmpBuf[128] = {0};
455 VENDOR_DEVICE_PATH *venPath = NULL;
456
457 venPath = (VENDOR_DEVICE_PATH *)TmpBuf;
458 NameLen = StrSize(VTOY_BLOCK_DEVICE_PATH_NAME);
459 venPath->Header.Type = HARDWARE_DEVICE_PATH;
460 venPath->Header.SubType = HW_VENDOR_DP;
461 venPath->Header.Length[0] = sizeof(VENDOR_DEVICE_PATH) + NameLen;
462 venPath->Header.Length[1] = 0;
463 CopyMem(&venPath->Guid, &gVtoyBlockDevicePathGuid, sizeof(EFI_GUID));
464 CopyMem(venPath + 1, VTOY_BLOCK_DEVICE_PATH_NAME, NameLen);
465
466 gBlockData.Path = AppendDevicePathNode(NULL, (EFI_DEVICE_PATH_PROTOCOL *)TmpBuf);
467 gBlockData.DevicePathCompareLen = sizeof(VENDOR_DEVICE_PATH) + NameLen;
468
469 debug("gBlockData.Path=<%s>\n", ConvertDevicePathToText(gBlockData.Path, FALSE, FALSE));
470
471 return EFI_SUCCESS;
472 }
473
474 EFI_STATUS EFIAPI ventoy_connect_driver(IN EFI_HANDLE ControllerHandle, IN CONST CHAR16 *DrvName)
475 {
476 UINTN i = 0;
477 UINTN Count = 0;
478 CHAR16 *DriverName = NULL;
479 EFI_HANDLE *Handles = NULL;
480 EFI_HANDLE DrvHandles[2] = { NULL };
481 EFI_STATUS Status = EFI_SUCCESS;
482 EFI_COMPONENT_NAME_PROTOCOL *NameProtocol = NULL;
483 EFI_COMPONENT_NAME2_PROTOCOL *Name2Protocol = NULL;
484
485 debug("ventoy_connect_driver <%s>...", DrvName);
486
487 Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiComponentName2ProtocolGuid,
488 NULL, &Count, &Handles);
489 if (EFI_ERROR(Status))
490 {
491 return Status;
492 }
493
494 for (i = 0; i < Count; i++)
495 {
496 Status = gBS->HandleProtocol(Handles[i], &gEfiComponentName2ProtocolGuid, (VOID **)&Name2Protocol);
497 if (EFI_ERROR(Status))
498 {
499 continue;
500 }
501
502 Status = Name2Protocol->GetDriverName(Name2Protocol, "en", &DriverName);
503 if (EFI_ERROR(Status) || NULL == DriverName)
504 {
505 continue;
506 }
507
508 if (StrStr(DriverName, DrvName))
509 {
510 debug("Find driver name2:<%s>: <%s>", DriverName, DrvName);
511 DrvHandles[0] = Handles[i];
512 break;
513 }
514 }
515
516 if (i < Count)
517 {
518 Status = gBS->ConnectController(ControllerHandle, DrvHandles, NULL, TRUE);
519 debug("ventoy_connect_driver:<%s> <%r>", DrvName, Status);
520 goto end;
521 }
522
523 debug("%s NOT found, now try COMPONENT_NAME", DrvName);
524
525 Count = 0;
526 FreePool(Handles);
527 Handles = NULL;
528
529 Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiComponentNameProtocolGuid,
530 NULL, &Count, &Handles);
531 if (EFI_ERROR(Status))
532 {
533 return Status;
534 }
535
536 for (i = 0; i < Count; i++)
537 {
538 Status = gBS->HandleProtocol(Handles[i], &gEfiComponentNameProtocolGuid, (VOID **)&NameProtocol);
539 if (EFI_ERROR(Status))
540 {
541 continue;
542 }
543
544 Status = NameProtocol->GetDriverName(NameProtocol, "en", &DriverName);
545 if (EFI_ERROR(Status))
546 {
547 continue;
548 }
549
550 if (StrStr(DriverName, DrvName))
551 {
552 debug("Find driver name:<%s>: <%s>", DriverName, DrvName);
553 DrvHandles[0] = Handles[i];
554 break;
555 }
556 }
557
558 if (i < Count)
559 {
560 Status = gBS->ConnectController(ControllerHandle, DrvHandles, NULL, TRUE);
561 debug("ventoy_connect_driver:<%s> <%r>", DrvName, Status);
562 goto end;
563 }
564
565 Status = EFI_NOT_FOUND;
566
567 end:
568 FreePool(Handles);
569
570 return Status;
571 }
572
573 EFI_STATUS EFIAPI ventoy_install_blockio(IN EFI_HANDLE ImageHandle, IN UINT64 ImgSize)
574 {
575 EFI_STATUS Status = EFI_SUCCESS;
576 EFI_BLOCK_IO_PROTOCOL *pBlockIo = &(gBlockData.BlockIo);
577
578 ventoy_fill_device_path();
579
580 debug("install block io protocol %p", ImageHandle);
581 ventoy_debug_pause();
582
583 gBlockData.Media.BlockSize = 2048;
584 gBlockData.Media.LastBlock = ImgSize / 2048 - 1;
585 gBlockData.Media.ReadOnly = TRUE;
586 gBlockData.Media.MediaPresent = 1;
587 gBlockData.Media.LogicalBlocksPerPhysicalBlock = 1;
588
589 pBlockIo->Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3;
590 pBlockIo->Media = &(gBlockData.Media);
591 pBlockIo->Reset = ventoy_block_io_reset;
592 pBlockIo->ReadBlocks = gMemdiskMode ? ventoy_block_io_ramdisk_read : ventoy_block_io_read;
593 pBlockIo->WriteBlocks = ventoy_block_io_write;
594 pBlockIo->FlushBlocks = ventoy_block_io_flush;
595
596 Status = gBS->InstallMultipleProtocolInterfaces(&gBlockData.Handle,
597 &gEfiBlockIoProtocolGuid, &gBlockData.BlockIo,
598 &gEfiDevicePathProtocolGuid, gBlockData.Path,
599 NULL);
600 debug("Install protocol %r %p", Status, gBlockData.Handle);
601 if (EFI_ERROR(Status))
602 {
603 return Status;
604 }
605
606 Status = ventoy_connect_driver(gBlockData.Handle, L"Disk I/O Driver");
607 debug("Connect disk IO driver %r", Status);
608
609 Status = ventoy_connect_driver(gBlockData.Handle, L"Partition Driver");
610 debug("Connect partition driver %r", Status);
611 if (EFI_ERROR(Status))
612 {
613 Status = gBS->ConnectController(gBlockData.Handle, NULL, NULL, TRUE);
614 debug("Connect all controller %r", Status);
615 }
616
617 ventoy_debug_pause();
618
619 return EFI_SUCCESS;
620 }
621
622 #if 0
623 /* For file replace */
624 #endif
625
626 STATIC EFI_STATUS EFIAPI
627 ventoy_wrapper_fs_open(EFI_FILE_HANDLE This, EFI_FILE_HANDLE *New, CHAR16 *Name, UINT64 Mode, UINT64 Attributes)
628 {
629 (VOID)This;
630 (VOID)New;
631 (VOID)Name;
632 (VOID)Mode;
633 (VOID)Attributes;
634 return EFI_SUCCESS;
635 }
636
637 STATIC EFI_STATUS EFIAPI
638 ventoy_wrapper_file_open_ex(EFI_FILE_HANDLE This, EFI_FILE_HANDLE *New, CHAR16 *Name, UINT64 Mode, UINT64 Attributes, EFI_FILE_IO_TOKEN *Token)
639 {
640 return ventoy_wrapper_fs_open(This, New, Name, Mode, Attributes);
641 }
642
643 STATIC EFI_STATUS EFIAPI
644 ventoy_wrapper_file_delete(EFI_FILE_HANDLE This)
645 {
646 (VOID)This;
647 return EFI_SUCCESS;
648 }
649
650 STATIC EFI_STATUS EFIAPI
651 ventoy_wrapper_file_set_info(EFI_FILE_HANDLE This, EFI_GUID *Type, UINTN Len, VOID *Data)
652 {
653 return EFI_SUCCESS;
654 }
655
656 STATIC EFI_STATUS EFIAPI
657 ventoy_wrapper_file_flush(EFI_FILE_HANDLE This)
658 {
659 (VOID)This;
660 return EFI_SUCCESS;
661 }
662
663 /* Ex version */
664 STATIC EFI_STATUS EFIAPI
665 ventoy_wrapper_file_flush_ex(EFI_FILE_HANDLE This, EFI_FILE_IO_TOKEN *Token)
666 {
667 (VOID)This;
668 (VOID)Token;
669 return EFI_SUCCESS;
670 }
671
672
673 STATIC EFI_STATUS EFIAPI
674 ventoy_wrapper_file_write(EFI_FILE_HANDLE This, UINTN *Len, VOID *Data)
675 {
676 (VOID)This;
677 (VOID)Len;
678 (VOID)Data;
679
680 return EFI_WRITE_PROTECTED;
681 }
682
683 STATIC EFI_STATUS EFIAPI
684 ventoy_wrapper_file_write_ex(IN EFI_FILE_PROTOCOL *This, IN OUT EFI_FILE_IO_TOKEN *Token)
685 {
686 return ventoy_wrapper_file_write(This, &(Token->BufferSize), Token->Buffer);
687 }
688
689
690 STATIC EFI_STATUS EFIAPI
691 ventoy_wrapper_file_close(EFI_FILE_HANDLE This)
692 {
693 (VOID)This;
694 return EFI_SUCCESS;
695 }
696
697
698 STATIC EFI_STATUS EFIAPI
699 ventoy_wrapper_file_set_pos(EFI_FILE_HANDLE This, UINT64 Position)
700 {
701 (VOID)This;
702
703 g_efi_file_replace.CurPos = Position;
704 return EFI_SUCCESS;
705 }
706
707 STATIC EFI_STATUS EFIAPI
708 ventoy_wrapper_file_get_pos(EFI_FILE_HANDLE This, UINT64 *Position)
709 {
710 (VOID)This;
711
712 *Position = g_efi_file_replace.CurPos;
713
714 return EFI_SUCCESS;
715 }
716
717
718 STATIC EFI_STATUS EFIAPI
719 ventoy_wrapper_file_get_info(EFI_FILE_HANDLE This, EFI_GUID *Type, UINTN *Len, VOID *Data)
720 {
721 EFI_FILE_INFO *Info = (EFI_FILE_INFO *) Data;
722
723 debug("ventoy_wrapper_file_get_info ... %u", *Len);
724
725 if (!CompareGuid(Type, &gEfiFileInfoGuid))
726 {
727 return EFI_INVALID_PARAMETER;
728 }
729
730 if (*Len == 0)
731 {
732 *Len = 384;
733 return EFI_BUFFER_TOO_SMALL;
734 }
735
736 ZeroMem(Data, sizeof(EFI_FILE_INFO));
737
738 Info->Size = sizeof(EFI_FILE_INFO);
739 Info->FileSize = g_efi_file_replace.FileSizeBytes;
740 Info->PhysicalSize = g_efi_file_replace.FileSizeBytes;
741 Info->Attribute = EFI_FILE_READ_ONLY;
742 //Info->FileName = EFI_FILE_READ_ONLY;
743
744 *Len = Info->Size;
745
746 return EFI_SUCCESS;
747 }
748
749 STATIC EFI_STATUS EFIAPI
750 ventoy_wrapper_file_read(EFI_FILE_HANDLE This, UINTN *Len, VOID *Data)
751 {
752 EFI_LBA Lba;
753 UINTN ReadLen = *Len;
754
755 (VOID)This;
756
757 debug("ventoy_wrapper_file_read ... %u", *Len);
758
759 if (g_efi_file_replace.CurPos + ReadLen > g_efi_file_replace.FileSizeBytes)
760 {
761 ReadLen = g_efi_file_replace.FileSizeBytes - g_efi_file_replace.CurPos;
762 }
763
764 Lba = g_efi_file_replace.CurPos / 2048 + g_efi_file_replace.BlockIoSectorStart;
765
766 ventoy_block_io_read(NULL, 0, Lba, ReadLen, Data);
767
768 *Len = ReadLen;
769
770 g_efi_file_replace.CurPos += ReadLen;
771
772 return EFI_SUCCESS;
773 }
774
775 STATIC EFI_STATUS EFIAPI
776 ventoy_wrapper_file_read_ex(IN EFI_FILE_PROTOCOL *This, IN OUT EFI_FILE_IO_TOKEN *Token)
777 {
778 return ventoy_wrapper_file_read(This, &(Token->BufferSize), Token->Buffer);
779 }
780
781 STATIC EFI_STATUS EFIAPI ventoy_wrapper_file_procotol(EFI_FILE_PROTOCOL *File)
782 {
783 File->Revision = EFI_FILE_PROTOCOL_REVISION2;
784 File->Open = ventoy_wrapper_fs_open;
785 File->Close = ventoy_wrapper_file_close;
786 File->Delete = ventoy_wrapper_file_delete;
787 File->Read = ventoy_wrapper_file_read;
788 File->Write = ventoy_wrapper_file_write;
789 File->GetPosition = ventoy_wrapper_file_get_pos;
790 File->SetPosition = ventoy_wrapper_file_set_pos;
791 File->GetInfo = ventoy_wrapper_file_get_info;
792 File->SetInfo = ventoy_wrapper_file_set_info;
793 File->Flush = ventoy_wrapper_file_flush;
794 File->OpenEx = ventoy_wrapper_file_open_ex;
795 File->ReadEx = ventoy_wrapper_file_read_ex;
796 File->WriteEx = ventoy_wrapper_file_write_ex;
797 File->FlushEx = ventoy_wrapper_file_flush_ex;
798
799 return EFI_SUCCESS;
800 }
801
802 STATIC EFI_STATUS EFIAPI ventoy_wrapper_file_open
803 (
804 EFI_FILE_HANDLE This,
805 EFI_FILE_HANDLE *New,
806 CHAR16 *Name,
807 UINT64 Mode,
808 UINT64 Attributes
809 )
810 {
811 UINT32 i = 0;
812 UINT32 j = 0;
813 UINT64 Sectors = 0;
814 EFI_STATUS Status = EFI_SUCCESS;
815 CHAR8 TmpName[256];
816 ventoy_virt_chunk *virt = NULL;
817
818 Status = g_original_fopen(This, New, Name, Mode, Attributes);
819 if (EFI_ERROR(Status))
820 {
821 return Status;
822 }
823
824 if (g_file_replace_list && g_file_replace_list->magic == GRUB_FILE_REPLACE_MAGIC &&
825 g_file_replace_list->new_file_virtual_id < g_virt_chunk_num)
826 {
827 AsciiSPrint(TmpName, sizeof(TmpName), "%s", Name);
828 for (j = 0; j < 4; j++)
829 {
830 if (0 == AsciiStrCmp(g_file_replace_list[i].old_file_name[j], TmpName))
831 {
832 g_original_fclose(*New);
833 *New = &g_efi_file_replace.WrapperHandle;
834 ventoy_wrapper_file_procotol(*New);
835
836 virt = g_virt_chunk + g_file_replace_list->new_file_virtual_id;
837
838 Sectors = (virt->mem_sector_end - virt->mem_sector_start) + (virt->remap_sector_end - virt->remap_sector_start);
839
840 g_efi_file_replace.BlockIoSectorStart = virt->mem_sector_start;
841 g_efi_file_replace.FileSizeBytes = Sectors * 2048;
842
843 if (gDebugPrint)
844 {
845 debug("## ventoy_wrapper_file_open <%s> BlockStart:%lu Sectors:%lu Bytes:%lu", Name,
846 g_efi_file_replace.BlockIoSectorStart, Sectors, Sectors * 2048);
847 sleep(3);
848 }
849
850 return Status;
851 }
852 }
853 }
854
855 return Status;
856 }
857
858 EFI_STATUS EFIAPI ventoy_wrapper_open_volume
859 (
860 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
861 OUT EFI_FILE_PROTOCOL **Root
862 )
863 {
864 EFI_STATUS Status = EFI_SUCCESS;
865
866 Status = g_original_open_volume(This, Root);
867 if (!EFI_ERROR(Status))
868 {
869 g_original_fopen = (*Root)->Open;
870 g_original_fclose = (*Root)->Close;
871 (*Root)->Open = ventoy_wrapper_file_open;
872 }
873
874 return Status;
875 }
876
877 EFI_STATUS EFIAPI ventoy_wrapper_push_openvolume(IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME OpenVolume)
878 {
879 g_original_open_volume = OpenVolume;
880 return EFI_SUCCESS;
881 }
882
883 #if 0
884 /* For auto skip Windows 'Press any key to boot from CD or DVD ...' */
885 #endif
886
887 STATIC EFI_STATUS EFIAPI ventoy_wrapper_read_key_ex
888 (
889 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
890 OUT EFI_KEY_DATA *KeyData
891 )
892 {
893 /* only hook once before BCD file read */
894 if (g_keyboard_hook_count == 0 && g_blockio_bcd_read_done == FALSE)
895 {
896 g_keyboard_hook_count++;
897
898 KeyData->Key.ScanCode = SCAN_DELETE;
899 KeyData->Key.UnicodeChar = 0;
900 KeyData->KeyState.KeyShiftState = 0;
901 KeyData->KeyState.KeyToggleState = 0;
902
903 return EFI_SUCCESS;
904 }
905
906 return g_org_read_key_ex(This, KeyData);
907 }
908
909 EFI_STATUS EFIAPI ventoy_wrapper_read_key
910 (
911 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
912 OUT EFI_INPUT_KEY *Key
913 )
914 {
915 /* only hook once before BCD file read */
916 if (g_keyboard_hook_count == 0 && g_blockio_bcd_read_done == FALSE)
917 {
918 g_keyboard_hook_count++;
919
920 Key->ScanCode = SCAN_DELETE;
921 Key->UnicodeChar = 0;
922 return EFI_SUCCESS;
923 }
924
925 return g_org_read_key(This, Key);
926 }
927
928 EFI_STATUS ventoy_hook_keyboard_start(VOID)
929 {
930 g_blockio_start_record_bcd = TRUE;
931 g_blockio_bcd_read_done = FALSE;
932 g_keyboard_hook_count = 0;
933
934 if (g_con_simple_input_ex)
935 {
936 g_org_read_key_ex = g_con_simple_input_ex->ReadKeyStrokeEx;
937 g_con_simple_input_ex->ReadKeyStrokeEx = ventoy_wrapper_read_key_ex;
938 }
939
940 g_org_read_key = gST->ConIn->ReadKeyStroke;
941 gST->ConIn->ReadKeyStroke = ventoy_wrapper_read_key;
942
943 return EFI_SUCCESS;
944 }
945
946 EFI_STATUS ventoy_hook_keyboard_stop(VOID)
947 {
948 g_blockio_start_record_bcd = FALSE;
949 g_blockio_bcd_read_done = FALSE;
950 g_keyboard_hook_count = 0;
951
952 if (g_con_simple_input_ex)
953 {
954 g_con_simple_input_ex->ReadKeyStrokeEx = g_org_read_key_ex;
955 }
956
957 gST->ConIn->ReadKeyStroke = g_org_read_key;
958
959 return EFI_SUCCESS;
960 }
961
962 #if 0
963 /* Fixup the 1st cdrom influnce for Windows boot */
964 #endif
965
966 STATIC EFI_STATUS EFIAPI ventoy_wrapper_locate_handle
967 (
968 IN EFI_LOCATE_SEARCH_TYPE SearchType,
969 IN EFI_GUID *Protocol, OPTIONAL
970 IN VOID *SearchKey, OPTIONAL
971 IN OUT UINTN *BufferSize,
972 OUT EFI_HANDLE *Buffer
973 )
974 {
975 UINTN i;
976 EFI_HANDLE Handle = NULL;
977 EFI_STATUS Status = EFI_SUCCESS;
978
979 Status = g_org_locate_handle(SearchType, Protocol, SearchKey, BufferSize, Buffer);
980
981 if (EFI_SUCCESS == Status && Protocol && CompareGuid(&gEfiBlockIoProtocolGuid, Protocol))
982 {
983 for (i = 0; i < (*BufferSize) / sizeof(EFI_HANDLE); i++)
984 {
985 if (Buffer[i] == gBlockData.Handle)
986 {
987 Handle = Buffer[0];
988 Buffer[0] = Buffer[i];
989 Buffer[i] = Handle;
990 break;
991 }
992 }
993 }
994
995 return Status;
996 }
997
998 EFI_STATUS ventoy_hook_1st_cdrom_start(VOID)
999 {
1000 g_org_locate_handle = gBS->LocateHandle;
1001 gBS->LocateHandle = ventoy_wrapper_locate_handle;
1002
1003 return EFI_SUCCESS;
1004 }
1005
1006 EFI_STATUS ventoy_hook_1st_cdrom_stop(VOID)
1007 {
1008 gBS->LocateHandle = g_org_locate_handle;
1009 g_org_locate_handle = NULL;
1010
1011 return EFI_SUCCESS;
1012 }
1013