+static int ventoy_video_hook(const struct grub_video_mode_info *info, void *hook_arg)
+{
+ int i;
+
+ (void)hook_arg;
+
+ if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PURE_TEXT)
+ {
+ return 0;
+ }
+
+ for (i = 0; i < g_video_mode_num; i++)
+ {
+ if (g_video_mode_list[i].width == info->width &&
+ g_video_mode_list[i].height == info->height &&
+ g_video_mode_list[i].bpp == info->bpp)
+ {
+ return 0;
+ }
+ }
+
+ g_video_mode_list[g_video_mode_num].width = info->width;
+ g_video_mode_list[g_video_mode_num].height = info->height;
+ g_video_mode_list[g_video_mode_num].bpp = info->bpp;
+ g_video_mode_num++;
+
+ if (g_video_mode_num == g_video_mode_max)
+ {
+ g_video_mode_max *= 2;
+ g_video_mode_list = grub_realloc(g_video_mode_list, g_video_mode_max * sizeof(ventoy_video_mode));
+ }
+
+ return 0;
+}
+
+static int ventoy_video_mode_cmp(ventoy_video_mode *v1, ventoy_video_mode *v2)
+{
+ if (v1->bpp == v2->bpp)
+ {
+ if (v1->width == v2->width)
+ {
+ if (v1->height == v2->height)
+ {
+ return 0;
+ }
+ else
+ {
+ return (v1->height < v2->height) ? -1 : 1;
+ }
+ }
+ else
+ {
+ return (v1->width < v2->width) ? -1 : 1;
+ }
+ }
+ else
+ {
+ return (v1->bpp < v2->bpp) ? -1 : 1;
+ }
+}
+
+static int ventoy_enum_video_mode(void)
+{
+ int i, j;
+ grub_video_adapter_t adapter;
+ grub_video_driver_id_t id;
+ ventoy_video_mode mode;
+
+ g_video_mode_num = 0;
+ g_video_mode_max = 1024;
+ g_video_mode_list = grub_malloc(sizeof(ventoy_video_mode) * g_video_mode_max);
+ if (!g_video_mode_list)
+ {
+ return 0;
+ }
+
+ #ifdef GRUB_MACHINE_PCBIOS
+ grub_dl_load ("vbe");
+ #endif
+
+ id = grub_video_get_driver_id ();
+
+ FOR_VIDEO_ADAPTERS (adapter)
+ {
+ if (!adapter->iterate ||
+ (adapter->id != id && (id != GRUB_VIDEO_DRIVER_NONE ||
+ adapter->init() != GRUB_ERR_NONE)))
+ {
+ continue;
+ }
+
+ adapter->iterate(ventoy_video_hook, NULL);
+
+ if (adapter->id != id)
+ {
+ adapter->fini();
+ }
+ }
+
+ /* sort video mode */
+ for (i = 0; i < g_video_mode_num; i++)
+ for (j = i + 1; j < g_video_mode_num; j++)
+ {
+ if (ventoy_video_mode_cmp(g_video_mode_list + i, g_video_mode_list + j) < 0)
+ {
+ grub_memcpy(&mode, g_video_mode_list + i, sizeof(ventoy_video_mode));
+ grub_memcpy(g_video_mode_list + i, g_video_mode_list + j, sizeof(ventoy_video_mode));
+ grub_memcpy(g_video_mode_list + j, &mode, sizeof(ventoy_video_mode));
+ }
+ }
+
+ VENTOY_CMD_RETURN(GRUB_ERR_NONE);
+}
+