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