]> glassweightruler.freedombox.rocks Git - Ventoy.git/blobdiff - EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.c
Add support for boot conf replace for distro which use systemd-boot in UEFI mode.
[Ventoy.git] / EDK2 / edk2_mod / edk2-edk2-stable201911 / MdeModulePkg / Application / Ventoy / Ventoy.c
index 7a06d76126b0aca7e929b3c498a7f5b15bde4280..cfcf41059dfd8d6b9b137731a3b7e4ff0c8ef98d 100644 (file)
 #include <Protocol/BlockIo.h>
 #include <Protocol/RamDisk.h>
 #include <Protocol/SimpleFileSystem.h>
+#include <Protocol/DriverBinding.h>
 #include <Ventoy.h>
 
 BOOLEAN gDebugPrint = FALSE;
+BOOLEAN gBootFallBack = FALSE;
 BOOLEAN gDotEfiBoot = FALSE;
 BOOLEAN gLoadIsoEfi = FALSE;
+BOOLEAN gIsoUdf = FALSE;
 ventoy_ram_disk g_ramdisk_param;
 ventoy_chain_head *g_chain;
+void *g_vtoy_img_location_buf;
 ventoy_img_chunk *g_chunk;
 UINT8 *g_os_param_reserved;
 UINT32 g_img_chunk_num;
@@ -55,7 +59,11 @@ 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;
 
+ventoy_grub_param_file_replace *g_img_replace_list = NULL;
+ventoy_efi_file_replace g_img_file_replace;
+
 CONST CHAR16 gIso9660EfiDriverPath[] = ISO9660_EFI_DRIVER_PATH;
+CONST CHAR16 gUdfEfiDriverPath[] = UDF_EFI_DRIVER_PATH;
 
 BOOLEAN g_fix_windows_1st_cdrom_issue = FALSE;
 
@@ -69,10 +77,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, ...)
@@ -249,6 +275,7 @@ static int ventoy_update_image_location(ventoy_os_param *param)
     }
 
     address = (UINTN)buffer;
+    g_vtoy_img_location_buf = buffer;
 
     if (address % 4096)
     {
@@ -273,19 +300,33 @@ static int ventoy_update_image_location(ventoy_os_param *param)
     }
 
     CopyMem(&location->guid, &param->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;
@@ -325,10 +366,22 @@ EFI_HANDLE EFIAPI ventoy_get_parent_handle(IN EFI_DEVICE_PATH_PROTOCOL *pDevPath
     return Handle;
 }
 
+STATIC ventoy_ram_disk g_backup_ramdisk_param;
+STATIC ventoy_os_param g_backup_os_param_var;
+
+
 EFI_STATUS EFIAPI ventoy_save_ramdisk_param(VOID)
 {
+    UINTN DataSize;
     EFI_STATUS Status = EFI_SUCCESS;
     EFI_GUID VarGuid = VENTOY_GUID;
+
+    DataSize = sizeof(g_backup_ramdisk_param);
+    Status = gRT->GetVariable(L"VentoyRamDisk", &VarGuid, NULL, &DataSize, &g_backup_ramdisk_param);
+    if (!EFI_ERROR(Status))
+    {
+        debug("find previous ramdisk variable <%llu>", g_backup_ramdisk_param.DiskSize);
+    }
     
     Status = gRT->SetVariable(L"VentoyRamDisk", &VarGuid, 
                   EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
@@ -342,21 +395,38 @@ EFI_STATUS EFIAPI ventoy_delete_ramdisk_param(VOID)
 {
     EFI_STATUS Status = EFI_SUCCESS;
     EFI_GUID VarGuid = VENTOY_GUID;
-    
-    Status = gRT->SetVariable(L"VentoyRamDisk", &VarGuid, 
+
+    if (g_backup_ramdisk_param.DiskSize > 0 && g_backup_ramdisk_param.PhyAddr > 0)
+    {
+        Status = gRT->SetVariable(L"VentoyRamDisk", &VarGuid, 
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+                  sizeof(g_backup_ramdisk_param), &g_backup_ramdisk_param);
+        debug("resotre ramdisk variable %r", Status);
+    }
+    else
+    {
+        Status = gRT->SetVariable(L"VentoyRamDisk", &VarGuid, 
                   EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
                   0, NULL);
-    debug("delete efi variable %r", Status);
+        debug("delete ramdisk variable %r", Status);
+    }
 
     return Status;
 }
 
-
 EFI_STATUS EFIAPI ventoy_save_variable(VOID)
 {
+    UINTN DataSize;
     EFI_STATUS Status = EFI_SUCCESS;
     EFI_GUID VarGuid = VENTOY_GUID;
-    
+
+    DataSize = sizeof(g_backup_os_param_var);
+    Status = gRT->GetVariable(L"VentoyOsParam", &VarGuid, NULL, &DataSize, &g_backup_os_param_var);
+    if (!EFI_ERROR(Status))
+    {
+        debug("find previous efi variable <%a>", g_backup_os_param_var.vtoy_img_path);
+    }
+
     Status = gRT->SetVariable(L"VentoyOsParam", &VarGuid, 
                   EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
                   sizeof(g_chain->os_param), &(g_chain->os_param));
@@ -369,11 +439,21 @@ EFI_STATUS EFIAPI ventoy_delete_variable(VOID)
 {
     EFI_STATUS Status = EFI_SUCCESS;
     EFI_GUID VarGuid = VENTOY_GUID;
-    
-    Status = gRT->SetVariable(L"VentoyOsParam", &VarGuid, 
+
+    if (0 == CompareMem(&(g_backup_os_param_var.guid), &VarGuid, sizeof(EFI_GUID)))
+    {
+        Status = gRT->SetVariable(L"VentoyOsParam", &VarGuid, 
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+                  sizeof(g_backup_os_param_var), &(g_backup_os_param_var));
+        debug("restore efi variable %r", Status);
+    }
+    else
+    {
+        Status = gRT->SetVariable(L"VentoyOsParam", &VarGuid, 
                   EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
                   0, NULL);
-    debug("delete efi variable %r", Status);
+        debug("delete efi variable %r", Status);
+    }
 
     return Status;
 }
@@ -394,12 +474,12 @@ STATIC VOID ventoy_warn_invalid_device(VOID)
     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 officially supported.\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 continue to boot after 15 seconds ...... ");
+    gST->ConOut->OutputString(gST->ConOut, L"\r\n\r\nWill exit after 10 seconds ...... ");
 
-    sleep(15);
+    sleep(10);
 }
 #else
 STATIC VOID ventoy_warn_invalid_device(VOID)
@@ -594,12 +674,23 @@ 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";
-            
-    Status = ventoy_load_image(ImageHandle, gBlockData.pDiskFsDevPath, 
-                               gIso9660EfiDriverPath, 
-                               sizeof(gIso9660EfiDriverPath), 
-                               &Image);
-    debug("load iso efi driver status:%r", Status);
+
+    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)
     {
@@ -619,6 +710,35 @@ STATIC EFI_STATUS EFIAPI ventoy_load_isoefi_driver(IN EFI_HANDLE ImageHandle)
     return EFI_SUCCESS;
 }
 
+STATIC EFI_STATUS ventoy_proc_img_replace_name(ventoy_grub_param_file_replace *replace)
+{
+    UINT32 i;
+    char tmp[256];
+
+    if (replace->magic != GRUB_IMG_REPLACE_MAGIC)
+    {
+        return EFI_SUCCESS;
+    }
+
+    if (replace->old_file_name[0][0] == 0)
+    {
+        return EFI_SUCCESS;
+    }
+
+    AsciiStrCpyS(tmp, sizeof(tmp), replace->old_file_name[0]);
+    
+    for (i = 0; i < 256 && tmp[i]; i++)
+    {
+        if (tmp[i] == '/')
+        {
+            tmp[i] = '\\';
+        }
+    }
+
+    AsciiStrCpyS(replace->old_file_name[0], 256, tmp);
+    return EFI_SUCCESS;
+}
+
 STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
 {   
     UINT32 i = 0;
@@ -649,6 +769,11 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
         gDebugPrint = TRUE;
     }
     
+    if (StrStr(pCmdLine, L"fallback"))
+    {
+        gBootFallBack = TRUE;
+    }
+    
     if (StrStr(pCmdLine, L"dotefi"))
     {
         gDotEfiBoot = TRUE;
@@ -658,6 +783,11 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
     {
         gLoadIsoEfi = TRUE;
     }
+    
+    if (StrStr(pCmdLine, L"iso_udf"))
+    {
+        gIsoUdf = TRUE;
+    }
 
     pPos = StrStr(pCmdLine, L"FirstTry=@");
     if (pPos)
@@ -704,6 +834,7 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
     if (pEnv[0] != '0' || pEnv[1] != 0)
     {
         ventoy_warn_invalid_device();
+        return EFI_INVALID_PARAMETER;
     }
     
     g_file_replace_list = &pGrubParam->file_replace;
@@ -718,6 +849,19 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
         old_cnt > 3 ? g_file_replace_list->old_file_name[3] : ""
         );
 
+    g_img_replace_list = &pGrubParam->img_replace;
+    ventoy_proc_img_replace_name(g_img_replace_list);
+    old_cnt = g_img_replace_list->old_file_cnt;
+    debug("img replace: magic:0x%x virtid:%u name count:%u <%a> <%a> <%a> <%a>",
+        g_img_replace_list->magic,
+        g_img_replace_list->new_file_virtual_id,
+        old_cnt,
+        old_cnt > 0 ? g_img_replace_list->old_file_name[0] : "",
+        old_cnt > 1 ? g_img_replace_list->old_file_name[1] : "",
+        old_cnt > 2 ? g_img_replace_list->old_file_name[2] : "",
+        old_cnt > 3 ? g_img_replace_list->old_file_name[3] : ""
+        );
+    
     pPos = StrStr(pCmdLine, L"mem:");
     chain = (ventoy_chain_head *)StrHexToUintn(pPos + 4);
 
@@ -822,12 +966,15 @@ EFI_STATUS EFIAPI ventoy_clean_env(VOID)
 
     ventoy_delete_variable();
 
-    if (g_chain->os_param.vtoy_img_location_addr)
+    if (g_vtoy_img_location_buf)
     {
-        FreePool((VOID *)(UINTN)g_chain->os_param.vtoy_img_location_addr);
+        FreePool(g_vtoy_img_location_buf);
     }
 
-    FreePool(g_chain);
+    if (!gMemdiskMode)
+    {
+        FreePool(g_chain);        
+    }
 
     return EFI_SUCCESS;
 }
@@ -948,7 +1095,8 @@ EFI_STATUS EFIAPI ventoy_boot(IN EFI_HANDLE ImageHandle)
                 gST->ConIn->Reset(gST->ConIn, FALSE);
             }
             
-            if (g_file_replace_list && g_file_replace_list->magic == GRUB_FILE_REPLACE_MAGIC)
+            if ((g_file_replace_list && g_file_replace_list->magic == GRUB_FILE_REPLACE_MAGIC) ||
+                (g_img_replace_list && g_img_replace_list->magic == GRUB_IMG_REPLACE_MAGIC))
             {
                 ventoy_wrapper_push_openvolume(pFile->OpenVolume);
                 pFile->OpenVolume = ventoy_wrapper_open_volume;
@@ -979,7 +1127,7 @@ EFI_STATUS EFIAPI ventoy_boot(IN EFI_HANDLE ImageHandle)
             }
         
             debug("Fs not found, now wait and retry...");
-            sleep(2);
+            sleep(1);
         }
     }
 
@@ -1023,6 +1171,8 @@ EFI_STATUS EFIAPI VentoyEfiMain
         return Status;
     }
 
+    ventoy_disable_ex_filesystem();
+
     if (gMemdiskMode)
     {
         g_ramdisk_param.PhyAddr = (UINT64)(UINTN)g_iso_data_buf;
@@ -1079,7 +1229,7 @@ EFI_STATUS EFIAPI VentoyEfiMain
         ventoy_clean_env();
     }
 
-    if (FALSE == gDotEfiBoot)
+    if (FALSE == gDotEfiBoot && FALSE == gBootFallBack)
     {
         if (EFI_NOT_FOUND == Status)
         {
@@ -1097,6 +1247,8 @@ EFI_STATUS EFIAPI VentoyEfiMain
         grub_env_set("vtoy_dotefi_retry", "YES");            
     }
 
+    ventoy_enable_ex_filesystem();
+
     return EFI_SUCCESS;
 }