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