vgabios: Unify code to generate the vbe mode list.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
diff --git a/vgasrc/bochsvga.c b/vgasrc/bochsvga.c
index d1919ec..5ab1bc2 100644
--- a/vgasrc/bochsvga.c
+++ b/vgasrc/bochsvga.c
@@ -199,26 +199,20 @@
     return 1;
 }
 
-int
-bochsvga_list_modes(u16 seg, u16 ptr)
+void
+bochsvga_list_modes(u16 seg, u16 *dest, u16 *last)
 {
-    int count = 0;
-    u16 *dest = (u16 *)(u32)ptr;
-
     struct bochsvga_mode *m = bochsvga_modes;
-    for (; m < &bochsvga_modes[ARRAY_SIZE(bochsvga_modes)]; m++) {
+    for (; m < &bochsvga_modes[ARRAY_SIZE(bochsvga_modes)] && dest<last; m++) {
         if (!mode_valid(&m->info))
             continue;
 
         dprintf(1, "VBE found mode %x valid.\n", GET_GLOBAL(m->mode));
-        SET_FARVAR(seg, dest[count], GET_GLOBAL(m->mode));
-
-        count++;
+        SET_FARVAR(seg, *dest, GET_GLOBAL(m->mode));
+        dest++;
     }
 
-    SET_FARVAR(seg, dest[count], 0xffff); /* End of list */
-
-    return count;
+    stdvga_list_modes(seg, dest, last);
 }
 
 int
diff --git a/vgasrc/bochsvga.h b/vgasrc/bochsvga.h
index 963b0d3..c08f103 100644
--- a/vgasrc/bochsvga.h
+++ b/vgasrc/bochsvga.h
@@ -55,7 +55,7 @@
 int bochsvga_init(void);
 int bochsvga_enabled(void);
 u16 bochsvga_total_mem(void);
-int bochsvga_list_modes(u16 seg, u16 ptr);
+void bochsvga_list_modes(u16 seg, u16 *dest, u16 *last);
 struct vbe_modeinfo;
 int bochsvga_mode_info(u16 mode, struct vbe_modeinfo *info);
 void bochsvga_hires_enable(int enable);
diff --git a/vgasrc/clext.c b/vgasrc/clext.c
index 90d7924..90f37c8 100644
--- a/vgasrc/clext.c
+++ b/vgasrc/clext.c
@@ -566,6 +566,17 @@
     { 0x11a, 0x75 },
 };
 
+void
+clext_list_modes(u16 seg, u16 *dest, u16 *last)
+{
+    int i;
+    for (i=0; i<ARRAY_SIZE(cirrus_vesa_modelist) && dest<last; i++) {
+        SET_FARVAR(seg, *dest, GET_GLOBAL(cirrus_vesa_modelist[i].vesamode));
+        dest++;
+    }
+    stdvga_list_modes(seg, dest, last);
+}
+
 static u16
 cirrus_vesamode_to_mode(u16 vesamode)
 {
@@ -706,12 +717,9 @@
     SET_FARVAR(seg, info->total_memory, cirrus_get_memsize());
 
     u16 *destmode = (void*)info->reserved;
+    u16 *last = (void*)&info->reserved[sizeof(info->reserved)];
     SET_FARVAR(seg, info->video_mode, SEGOFF(seg, (u32)destmode));
-    int i;
-    for (i=0; i<ARRAY_SIZE(cirrus_vesa_modelist); i++)
-        SET_FARVAR(seg, destmode[i]
-                   , GET_GLOBAL(cirrus_vesa_modelist[i].vesamode));
-    SET_FARVAR(seg, destmode[i], 0xffff);
+    clext_list_modes(seg, destmode, last);
 
     regs->ax = 0x004f;
 }
diff --git a/vgasrc/clext.h b/vgasrc/clext.h
index e344639..f337b65 100644
--- a/vgasrc/clext.h
+++ b/vgasrc/clext.h
@@ -5,6 +5,7 @@
 
 struct vgamode_s *clext_find_mode(int mode);
 int clext_set_mode(int mode, int flags);
+void clext_list_modes(u16 seg, u16 *dest, u16 *last);
 int clext_init(void);
 
 #endif // clext.h
diff --git a/vgasrc/stdvga.c b/vgasrc/stdvga.c
index 70d018a..6998cd0 100644
--- a/vgasrc/stdvga.c
+++ b/vgasrc/stdvga.c
@@ -642,6 +642,12 @@
  ****************************************************************/
 
 void
+stdvga_list_modes(u16 seg, u16 *dest, u16 *last)
+{
+    SET_FARVAR(seg, *dest, 0xffff);
+}
+
+void
 stdvga_enable_video_addressing(u8 disable)
 {
     u8 v = (disable & 1) ? 0x00 : 0x02;
diff --git a/vgasrc/stdvga.h b/vgasrc/stdvga.h
index 4cef89f..033a711 100644
--- a/vgasrc/stdvga.h
+++ b/vgasrc/stdvga.h
@@ -119,6 +119,7 @@
 void stdvga_restore_state(u16 seg, struct saveVideoHardware *info);
 int stdvga_set_mode(int mode, int flags);
 void stdvga_enable_video_addressing(u8 disable);
+void stdvga_list_modes(u16 seg, u16 *dest, u16 *last);
 int stdvga_init(void);
 
 #endif // stdvga.h
diff --git a/vgasrc/vbe.c b/vgasrc/vbe.c
index 8256cae..daf8c51 100644
--- a/vgasrc/vbe.c
+++ b/vgasrc/vbe.c
@@ -39,7 +39,8 @@
     SET_FARVAR(seg, info->capabilities, 0x1); /* 8BIT DAC */
 
     /* We generate our mode list in the reserved field of the info block */
-    SET_FARVAR(seg, info->video_mode, SEGOFF(seg, regs->di + 34));
+    u16 *destmode = (void*)info->reserved;
+    SET_FARVAR(seg, info->video_mode, SEGOFF(seg, (u32)destmode));
 
     /* Total memory (in 64 blocks) */
     SET_FARVAR(seg, info->total_memory, bochsvga_total_mem());
@@ -52,7 +53,8 @@
             SEGOFF(get_global_seg(), (u32)VBE_REVISION_STRING));
 
     /* Fill list of modes */
-    bochsvga_list_modes(seg, regs->di + 32);
+    u16 *last = (void*)&info->reserved[sizeof(info->reserved)];
+    vgahw_list_modes(seg, destmode, last - 1);
 
     regs->al = regs->ah; /* 0x4F, Function supported */
     regs->ah = 0x0; /* 0x0, Function call successful */
diff --git a/vgasrc/vgahw.h b/vgasrc/vgahw.h
index 9d8a067..1101e51 100644
--- a/vgasrc/vgahw.h
+++ b/vgasrc/vgahw.h
@@ -25,6 +25,15 @@
     return stdvga_set_mode(mode, flags);
 }
 
+static inline void vgahw_list_modes(u16 seg, u16 *dest, u16 *last) {
+    if (CONFIG_VGA_CIRRUS)
+        clext_list_modes(seg, dest, last);
+    else if (CONFIG_VGA_BOCHS)
+        bochsvga_list_modes(seg, dest, last);
+    else
+        stdvga_list_modes(seg, dest, last);
+}
+
 static inline int vgahw_init(void) {
     if (CONFIG_VGA_CIRRUS)
         return clext_init();