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