X-Git-Url: https://glassweightruler.freedombox.rocks/gitweb/Ventoy.git/blobdiff_plain/1cbe4c81b4978311696ab4e9e8dffb7d98b82570..ee81f899117fbf16173430d2bd4dd164ecc2fb2f:/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.c diff --git a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.c b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.c index 7c2267f..c560bcb 100644 --- a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.c +++ b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.c @@ -37,6 +37,9 @@ #include BOOLEAN gDebugPrint = FALSE; +BOOLEAN gDotEfiBoot = FALSE; +BOOLEAN gLoadIsoEfi = FALSE; +BOOLEAN gIsoUdf = FALSE; ventoy_ram_disk g_ramdisk_param; ventoy_chain_head *g_chain; ventoy_img_chunk *g_chunk; @@ -48,10 +51,16 @@ ventoy_virt_chunk *g_virt_chunk; UINT32 g_virt_chunk_num; vtoy_block_data gBlockData; static grub_env_get_pf grub_env_get = NULL; +static grub_env_set_pf grub_env_set = NULL; ventoy_grub_param_file_replace *g_file_replace_list = NULL; ventoy_efi_file_replace g_efi_file_replace; +CONST CHAR16 gIso9660EfiDriverPath[] = ISO9660_EFI_DRIVER_PATH; +CONST CHAR16 gUdfEfiDriverPath[] = UDF_EFI_DRIVER_PATH; + +BOOLEAN g_fix_windows_1st_cdrom_issue = FALSE; + STATIC BOOLEAN g_hook_keyboard = FALSE; CHAR16 gFirstTryBootFile[256] = {0}; @@ -62,10 +71,28 @@ CONST CHAR16 *gEfiBootFileName[] = { L"@", EFI_REMOVABLE_MEDIA_FILE_NAME, +#if defined (MDE_CPU_IA32) + L"\\EFI\\BOOT\\GRUBIA32.EFI", + L"\\EFI\\BOOT\\BOOTia32.EFI", + L"\\EFI\\BOOT\\bootia32.efi", + L"\\efi\\boot\\bootia32.efi", +#elif defined (MDE_CPU_X64) L"\\EFI\\BOOT\\GRUBX64.EFI", L"\\EFI\\BOOT\\BOOTx64.EFI", L"\\EFI\\BOOT\\bootx64.efi", L"\\efi\\boot\\bootx64.efi", +#elif defined (MDE_CPU_ARM) + L"\\EFI\\BOOT\\GRUBARM.EFI", + L"\\EFI\\BOOT\\BOOTarm.EFI", + L"\\EFI\\BOOT\\bootarm.efi", + L"\\efi\\boot\\bootarm.efi", +#elif defined (MDE_CPU_AARCH64) + L"\\EFI\\BOOT\\GRUBAA64.EFI", + L"\\EFI\\BOOT\\BOOTaa64.EFI", + L"\\EFI\\BOOT\\bootaa64.efi", + L"\\efi\\boot\\bootaa64.efi", +#endif + }; VOID EFIAPI VtoyDebug(IN CONST CHAR8 *Format, ...) @@ -266,19 +293,33 @@ static int ventoy_update_image_location(ventoy_os_param *param) } CopyMem(&location->guid, ¶m->guid, sizeof(ventoy_guid)); - location->image_sector_size = 2048; + location->image_sector_size = gSector512Mode ? 512 : 2048; location->disk_sector_size = g_chain->disk_sector_size; location->region_count = g_img_chunk_num; region = location->regions; - for (i = 0; i < g_img_chunk_num; i++) + if (gSector512Mode) + { + for (i = 0; i < g_img_chunk_num; i++) + { + region->image_sector_count = chunk->disk_end_sector - chunk->disk_start_sector + 1; + region->image_start_sector = chunk->img_start_sector * 4; + region->disk_start_sector = chunk->disk_start_sector; + region++; + chunk++; + } + } + else { - region->image_sector_count = chunk->img_end_sector - chunk->img_start_sector + 1; - region->image_start_sector = chunk->img_start_sector; - region->disk_start_sector = chunk->disk_start_sector; - region++; - chunk++; + for (i = 0; i < g_img_chunk_num; i++) + { + region->image_sector_count = chunk->img_end_sector - chunk->img_start_sector + 1; + region->image_start_sector = chunk->img_start_sector; + region->disk_start_sector = chunk->disk_start_sector; + region++; + chunk++; + } } return 0; @@ -326,7 +367,7 @@ EFI_STATUS EFIAPI ventoy_save_ramdisk_param(VOID) Status = gRT->SetVariable(L"VentoyRamDisk", &VarGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, sizeof(g_ramdisk_param), &(g_ramdisk_param)); - debug("set efi variable %r", Status); + debug("set ramdisk variable %r", Status); return Status; } @@ -371,6 +412,36 @@ EFI_STATUS EFIAPI ventoy_delete_variable(VOID) return Status; } +#if (VENTOY_DEVICE_WARN != 0) +STATIC VOID ventoy_warn_invalid_device(VOID) +{ + STATIC BOOLEAN flag = FALSE; + + if (flag) + { + return; + } + + flag = TRUE; + gST->ConOut->ClearScreen(gST->ConOut); + gST->ConOut->OutputString(gST->ConOut, VTOY_WARNING L"\r\n"); + gST->ConOut->OutputString(gST->ConOut, VTOY_WARNING L"\r\n"); + gST->ConOut->OutputString(gST->ConOut, VTOY_WARNING L"\r\n\r\n\r\n"); + + gST->ConOut->OutputString(gST->ConOut, L"This is NOT a standard Ventoy device and is NOT supported.\r\n\r\n"); + gST->ConOut->OutputString(gST->ConOut, L"You should follow the official instructions in https://www.ventoy.net\r\n"); + + gST->ConOut->OutputString(gST->ConOut, L"\r\n\r\nWill exit after 10 seconds ...... "); + + sleep(10); +} +#else +STATIC VOID ventoy_warn_invalid_device(VOID) +{ + +} +#endif + STATIC EFI_STATUS EFIAPI ventoy_load_image ( IN EFI_HANDLE ImageHandle, @@ -413,6 +484,7 @@ STATIC EFI_STATUS EFIAPI ventoy_find_iso_disk(IN EFI_HANDLE ImageHandle) UINTN i = 0; UINTN Count = 0; UINT64 DiskSize = 0; + MBR_HEAD *pMBR = NULL; UINT8 *pBuffer = NULL; EFI_HANDLE *Handles; EFI_STATUS Status = EFI_SUCCESS; @@ -456,6 +528,18 @@ STATIC EFI_STATUS EFIAPI ventoy_find_iso_disk(IN EFI_HANDLE ImageHandle) if (CompareMem(g_chain->os_param.vtoy_disk_guid, pBuffer + 0x180, 16) == 0) { + pMBR = (MBR_HEAD *)pBuffer; + if (pMBR->PartTbl[0].FsFlag != 0xEE) + { + if (pMBR->PartTbl[0].StartSectorId != 2048 || + pMBR->PartTbl[1].SectorCount != 65536 || + pMBR->PartTbl[1].StartSectorId != pMBR->PartTbl[0].StartSectorId + pMBR->PartTbl[0].SectorCount) + { + debug("Failed to check disk part table"); + ventoy_warn_invalid_device(); + } + } + gBlockData.RawBlockIoHandle = Handles[i]; gBlockData.pRawBlockIo = pBlockIo; gBS->OpenProtocol(Handles[i], &gEfiDevicePathProtocolGuid, @@ -482,17 +566,117 @@ STATIC EFI_STATUS EFIAPI ventoy_find_iso_disk(IN EFI_HANDLE ImageHandle) } } + +STATIC EFI_STATUS EFIAPI ventoy_find_iso_disk_fs(IN EFI_HANDLE ImageHandle) +{ + UINTN i = 0; + UINTN Count = 0; + EFI_HANDLE Parent = NULL; + EFI_HANDLE *Handles = NULL; + EFI_STATUS Status = EFI_SUCCESS; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *pFile = NULL; + EFI_DEVICE_PATH_PROTOCOL *pDevPath = NULL; + + Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiSimpleFileSystemProtocolGuid, + NULL, &Count, &Handles); + if (EFI_ERROR(Status)) + { + return Status; + } + + debug("ventoy_find_iso_disk_fs fs count:%u", Count); + + for (i = 0; i < Count; i++) + { + Status = gBS->HandleProtocol(Handles[i], &gEfiSimpleFileSystemProtocolGuid, (VOID **)&pFile); + if (EFI_ERROR(Status)) + { + continue; + } + + Status = gBS->OpenProtocol(Handles[i], &gEfiDevicePathProtocolGuid, + (VOID **)&pDevPath, + ImageHandle, + Handles[i], + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (EFI_ERROR(Status)) + { + debug("Failed to open device path protocol %r", Status); + continue; + } + + debug("Handle:%p FS DP: <%s>", Handles[i], ConvertDevicePathToText(pDevPath, FALSE, FALSE)); + Parent = ventoy_get_parent_handle(pDevPath); + + if (Parent == gBlockData.RawBlockIoHandle) + { + debug("Find ventoy disk fs"); + gBlockData.DiskFsHandle = Handles[i]; + gBlockData.pDiskFs = pFile; + gBlockData.pDiskFsDevPath = pDevPath; + break; + } + } + + FreePool(Handles); + + return EFI_SUCCESS; +} + +STATIC EFI_STATUS EFIAPI ventoy_load_isoefi_driver(IN EFI_HANDLE ImageHandle) +{ + EFI_HANDLE Image = NULL; + EFI_STATUS Status = EFI_SUCCESS; + CHAR16 LogVar[4] = L"5"; + + if (gIsoUdf) + { + Status = ventoy_load_image(ImageHandle, gBlockData.pDiskFsDevPath, + gUdfEfiDriverPath, + sizeof(gUdfEfiDriverPath), + &Image); + debug("load iso UDF efi driver status:%r", Status); + } + else + { + Status = ventoy_load_image(ImageHandle, gBlockData.pDiskFsDevPath, + gIso9660EfiDriverPath, + sizeof(gIso9660EfiDriverPath), + &Image); + debug("load iso 9660 efi driver status:%r", Status); + } + + if (gDebugPrint) + { + gRT->SetVariable(L"FS_LOGGING", &gShellVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + sizeof(LogVar), LogVar); + } + + gRT->SetVariable(L"FS_NAME_NOCASE", &gShellVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + sizeof(LogVar), LogVar); + + gBlockData.IsoDriverImage = Image; + Status = gBS->StartImage(Image, NULL, NULL); + debug("Start iso efi driver status:%r", Status); + + return EFI_SUCCESS; +} + STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle) { UINT32 i = 0; UINT32 old_cnt = 0; UINTN size = 0; UINT8 chksum = 0; + const char *pEnv = NULL; CHAR16 *pPos = NULL; CHAR16 *pCmdLine = NULL; EFI_STATUS Status = EFI_SUCCESS; ventoy_grub_param *pGrubParam = NULL; EFI_LOADED_IMAGE_PROTOCOL *pImageInfo = NULL; + ventoy_chain_head *chain = NULL; Status = gBS->HandleProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&pImageInfo); if (EFI_ERROR(Status)) @@ -509,6 +693,21 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle) { gDebugPrint = TRUE; } + + if (StrStr(pCmdLine, L"dotefi")) + { + gDotEfiBoot = TRUE; + } + + if (StrStr(pCmdLine, L"isoefi=on")) + { + gLoadIsoEfi = TRUE; + } + + if (StrStr(pCmdLine, L"iso_udf")) + { + gIsoUdf = TRUE; + } pPos = StrStr(pCmdLine, L"FirstTry=@"); if (pPos) @@ -544,8 +743,20 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle) } pGrubParam = (ventoy_grub_param *)StrHexToUintn(pPos + StrLen(L"env_param=")); + grub_env_set = pGrubParam->grub_env_set; grub_env_get = pGrubParam->grub_env_get; + pEnv = grub_env_get("VTOY_CHKDEV_RESULT_STRING"); + if (!pEnv) + { + return EFI_INVALID_PARAMETER; + } + if (pEnv[0] != '0' || pEnv[1] != 0) + { + ventoy_warn_invalid_device(); + return EFI_INVALID_PARAMETER; + } + g_file_replace_list = &pGrubParam->file_replace; old_cnt = g_file_replace_list->old_file_cnt; debug("file replace: magic:0x%x virtid:%u name count:%u <%a> <%a> <%a> <%a>", @@ -559,20 +770,33 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle) ); pPos = StrStr(pCmdLine, L"mem:"); - g_chain = (ventoy_chain_head *)StrHexToUintn(pPos + 4); + chain = (ventoy_chain_head *)StrHexToUintn(pPos + 4); pPos = StrStr(pPos, L"size:"); size = StrDecimalToUintn(pPos + 5); - debug("memory addr:%p size:%lu", g_chain, size); + debug("memory addr:%p size:%lu", chain, size); + + if (StrStr(pCmdLine, L"sector512")) + { + gSector512Mode = TRUE; + } if (StrStr(pCmdLine, L"memdisk")) { - g_iso_buf_size = size; + g_iso_data_buf = (UINT8 *)chain + sizeof(ventoy_chain_head); + g_iso_buf_size = size - sizeof(ventoy_chain_head); + debug("memdisk mode iso_buf_size:%u", g_iso_buf_size); + + g_chain = chain; gMemdiskMode = TRUE; } else { + debug("This is normal mode"); + g_chain = AllocatePool(size); + CopyMem(g_chain, chain, size); + g_chunk = (ventoy_img_chunk *)((char *)g_chain + g_chain->img_chunk_offset); g_img_chunk_num = g_chain->img_chunk_num; g_override_chunk = (ventoy_override_chunk *)((char *)g_chain + g_chain->override_chunk_offset); @@ -583,12 +807,12 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle) g_os_param_reserved = (UINT8 *)(g_chain->os_param.vtoy_reserved); /* Workaround for Windows & ISO9660 */ - if (g_os_param_reserved[2] == 1 && g_os_param_reserved[3] == 0) + if (g_os_param_reserved[2] == ventoy_chain_windows && g_os_param_reserved[3] == 0) { g_fixup_iso9660_secover_enable = TRUE; } - if (g_os_param_reserved[2] == 1 && g_os_param_reserved[4] != 1) + if (g_os_param_reserved[2] == ventoy_chain_windows && g_os_param_reserved[4] != 1) { g_hook_keyboard = TRUE; } @@ -613,6 +837,19 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle) } } + g_fix_windows_1st_cdrom_issue = FALSE; + if (ventoy_chain_windows == g_os_param_reserved[2] || + ventoy_chain_wim == g_os_param_reserved[2]) + { + if (ventoy_is_cdrom_dp_exist()) + { + debug("fixup the 1st cdrom influences when boot windows ..."); + g_fix_windows_1st_cdrom_issue = TRUE; + } + } + + ventoy_debug_pause(); + FreePool(pCmdLine); return EFI_SUCCESS; } @@ -622,6 +859,11 @@ EFI_STATUS EFIAPI ventoy_clean_env(VOID) FreePool(g_sector_flag); g_sector_flag_num = 0; + if (gLoadIsoEfi && gBlockData.IsoDriverImage) + { + gBS->UnloadImage(gBlockData.IsoDriverImage); + } + gBS->DisconnectController(gBlockData.Handle, NULL, NULL); gBS->UninstallMultipleProtocolInterfaces(gBlockData.Handle, @@ -636,6 +878,44 @@ EFI_STATUS EFIAPI ventoy_clean_env(VOID) FreePool((VOID *)(UINTN)g_chain->os_param.vtoy_img_location_addr); } + FreePool(g_chain); + + return EFI_SUCCESS; +} + +STATIC EFI_STATUS ventoy_hook_start(VOID) +{ + /* don't add debug print in this function */ + + if (g_fix_windows_1st_cdrom_issue) + { + ventoy_hook_1st_cdrom_start(); + } + + /* let this the last */ + if (g_hook_keyboard) + { + ventoy_hook_keyboard_start(); + } + + return EFI_SUCCESS; +} + +STATIC EFI_STATUS ventoy_hook_stop(VOID) +{ + /* don't add debug print in this function */ + + if (g_fix_windows_1st_cdrom_issue) + { + ventoy_hook_1st_cdrom_stop(); + } + + /* let this the last */ + if (g_hook_keyboard) + { + ventoy_hook_keyboard_stop(); + } + return EFI_SUCCESS; } @@ -725,17 +1005,11 @@ EFI_STATUS EFIAPI ventoy_boot(IN EFI_HANDLE ImageHandle) pFile->OpenVolume = ventoy_wrapper_open_volume; } - if (g_hook_keyboard) - { - ventoy_hook_keyboard_start(); - } + ventoy_hook_start(); /* can't add debug print here */ //ventoy_wrapper_system(); Status = gBS->StartImage(Image, NULL, NULL); - if (g_hook_keyboard) - { - ventoy_hook_keyboard_stop(); - } + ventoy_hook_stop(); if (EFI_ERROR(Status)) { @@ -750,6 +1024,11 @@ EFI_STATUS EFIAPI ventoy_boot(IN EFI_HANDLE ImageHandle) if (Find == 0) { + if (gDotEfiBoot) + { + break; + } + debug("Fs not found, now wait and retry..."); sleep(2); } @@ -789,46 +1068,86 @@ EFI_STATUS EFIAPI VentoyEfiMain gST->ConOut->ClearScreen(gST->ConOut); ventoy_clear_input(); - ventoy_parse_cmdline(ImageHandle); + Status = ventoy_parse_cmdline(ImageHandle); + if (EFI_ERROR(Status)) + { + return Status; + } if (gMemdiskMode) { - g_ramdisk_param.PhyAddr = (UINT64)(UINTN)g_chain; + g_ramdisk_param.PhyAddr = (UINT64)(UINTN)g_iso_data_buf; g_ramdisk_param.DiskSize = (UINT64)g_iso_buf_size; ventoy_save_ramdisk_param(); + + if (gLoadIsoEfi) + { + ventoy_find_iso_disk(ImageHandle); + ventoy_find_iso_disk_fs(ImageHandle); + ventoy_load_isoefi_driver(ImageHandle); + } ventoy_install_blockio(ImageHandle, g_iso_buf_size); + ventoy_debug_pause(); + Status = ventoy_boot(ImageHandle); ventoy_delete_ramdisk_param(); + + if (gLoadIsoEfi && gBlockData.IsoDriverImage) + { + gBS->UnloadImage(gBlockData.IsoDriverImage); + } + + gBS->DisconnectController(gBlockData.Handle, NULL, NULL); + gBS->UninstallMultipleProtocolInterfaces(gBlockData.Handle, + &gEfiBlockIoProtocolGuid, &gBlockData.BlockIo, + &gEfiDevicePathProtocolGuid, gBlockData.Path, + NULL); } else { ventoy_save_variable(); - ventoy_find_iso_disk(ImageHandle); - - ventoy_debug_pause(); - - ventoy_install_blockio(ImageHandle, g_chain->virt_img_size_in_bytes); + Status = ventoy_find_iso_disk(ImageHandle); + if (!EFI_ERROR(Status)) + { + if (gLoadIsoEfi) + { + ventoy_find_iso_disk_fs(ImageHandle); + ventoy_load_isoefi_driver(ImageHandle); + } - ventoy_debug_pause(); + ventoy_debug_pause(); + + ventoy_install_blockio(ImageHandle, g_chain->virt_img_size_in_bytes); - Status = ventoy_boot(ImageHandle); + ventoy_debug_pause(); + Status = ventoy_boot(ImageHandle); + } + ventoy_clean_env(); } - if (EFI_NOT_FOUND == Status) + if (FALSE == gDotEfiBoot) { - gST->ConOut->OutputString(gST->ConOut, L"No bootfile found for UEFI!\r\n"); - gST->ConOut->OutputString(gST->ConOut, L"Maybe the image does not support " VENTOY_UEFI_DESC L"!\r\n"); - sleep(30); + if (EFI_NOT_FOUND == Status) + { + gST->ConOut->OutputString(gST->ConOut, L"No bootfile found for UEFI!\r\n"); + gST->ConOut->OutputString(gST->ConOut, L"Maybe the image does not support " VENTOY_UEFI_DESC L"!\r\n"); + sleep(30); + } } - + ventoy_clear_input(); gST->ConOut->ClearScreen(gST->ConOut); + if (gDotEfiBoot && (EFI_NOT_FOUND == Status)) + { + grub_env_set("vtoy_dotefi_retry", "YES"); + } + return EFI_SUCCESS; }