:: commit ea7904d13de80a369180ab9330ac814f2b0e208b

Mintsuki <mintsuki@protonmail.com> — 2026-03-22 19:03

parents: f2da88d3d0

protos/limine: Add Flanterm FB init params feature

diff --git a/common/lib/gterm.c b/common/lib/gterm.c
index ca944723..1f096b48 100644
--- a/common/lib/gterm.c
+++ b/common/lib/gterm.c
@@ -276,6 +276,8 @@ static const uint8_t builtin_font[] = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 };
 
+#define FONT_MAX 16384
+
 static struct image *background;
 
 static size_t margin = 64;
@@ -472,134 +474,88 @@ static void generate_canvas(struct fb_info *fb) {
         loop_internal(fb, effective_margin, gradient_stop_x, effective_margin, gradient_stop_y);
     } else {
         bg_canvas = NULL;
+        bg_canvas_size = 0;
     }
 }
 
 
-bool gterm_init(struct fb_info **_fbs, size_t *_fbs_count,
-                char *config, size_t width, size_t height) {
-    static struct fb_info *fbs;
-    static size_t fbs_count;
-
-    static bool prev_valid = false;
-    static char *prev_config;
-    static size_t prev_width, prev_height;
-
-    if (prev_valid && config == prev_config && width == prev_width && height == prev_height) {
-        *_fbs = fbs;
-        *_fbs_count = fbs_count;
-        reset_term();
-        return true;
-    }
-
-    prev_valid = false;
-
-    if (quiet) {
-        term_notready();
-        return false;
-    }
-
-#if defined (UEFI)
-    if (serial || COM_OUTPUT) {
-        term_fallback();
-        return true;
-    }
-#endif
-
-    term_notready();
-
-    // We force bpp to 32
-    fb_init(&fbs, &fbs_count, width, height, 32);
-
-    if (_fbs != NULL) {
-        *_fbs = fbs;
-    }
-    if (_fbs_count != NULL) {
-        *_fbs_count = fbs_count;
-    }
-
-    if (fbs_count == 0) {
-        return false;
+static void parse_palette(const char *str, uint32_t *colours) {
+    const char *first = str;
+    for (size_t i = 0; i < 8; i++) {
+        const char *last;
+        uint32_t col = strtoui(first, &last, 16);
+        if (first == last)
+            break;
+        colours[i] = col & 0xffffff;
+        if (*last == 0)
+            break;
+        first = last + 1;
     }
+}
 
-    // default scheme
-    margin = 64;
-    margin_gradient = 4;
+struct gterm_config {
+    int fb_rotation;
+    uint32_t ansi_colours[8];
+    uint32_t ansi_bright_colours[8];
+    char *theme_background;
+    uint8_t *font;
+    size_t font_width;
+    size_t font_height;
+    size_t font_size;
+    size_t font_spacing;
+    size_t font_scale_x;
+    size_t font_scale_y;
+    bool font_scale_is_default;
+};
 
-    int fb_rotation = FLANTERM_FB_ROTATE_0;
+static void gterm_parse_config(char *config, struct gterm_config *cfg) {
+    cfg->fb_rotation = FLANTERM_FB_ROTATE_0;
     char *rotation_str = config_get_value(config, 0, "INTERFACE_ROTATION");
     if (rotation_str != NULL) {
         int rotation_val = strtoui(rotation_str, NULL, 10);
         switch (rotation_val) {
-            case 90: fb_rotation = FLANTERM_FB_ROTATE_90; break;
-            case 180: fb_rotation = FLANTERM_FB_ROTATE_180; break;
-            case 270: fb_rotation = FLANTERM_FB_ROTATE_270; break;
+            case 90: cfg->fb_rotation = FLANTERM_FB_ROTATE_90; break;
+            case 180: cfg->fb_rotation = FLANTERM_FB_ROTATE_180; break;
+            case 270: cfg->fb_rotation = FLANTERM_FB_ROTATE_270; break;
         }
     }
 
-    uint32_t ansi_colours[8];
-
-    ansi_colours[0] = 0x00000000; // black
-    ansi_colours[1] = 0x00aa0000; // red
-    ansi_colours[2] = 0x0000aa00; // green
-    ansi_colours[3] = 0x00aa5500; // brown
-    ansi_colours[4] = 0x000000aa; // blue
-    ansi_colours[5] = 0x00aa00aa; // magenta
-    ansi_colours[6] = 0x0000aaaa; // cyan
-    ansi_colours[7] = 0x00aaaaaa; // grey
+    cfg->ansi_colours[0] = 0x00000000;
+    cfg->ansi_colours[1] = 0x00aa0000;
+    cfg->ansi_colours[2] = 0x0000aa00;
+    cfg->ansi_colours[3] = 0x00aa5500;
+    cfg->ansi_colours[4] = 0x000000aa;
+    cfg->ansi_colours[5] = 0x00aa00aa;
+    cfg->ansi_colours[6] = 0x0000aaaa;
+    cfg->ansi_colours[7] = 0x00aaaaaa;
 
     char *colours = config_get_value(config, 0, "TERM_PALETTE");
     if (colours != NULL) {
-        const char *first = colours;
-        size_t i;
-        for (i = 0; i < 8; i++) {
-            const char *last;
-            uint32_t col = strtoui(first, &last, 16);
-            if (first == last)
-                break;
-            ansi_colours[i] = col & 0xffffff;
-            if (*last == 0)
-                break;
-            first = last + 1;
-        }
+        parse_palette(colours, cfg->ansi_colours);
     }
 
-    uint32_t ansi_bright_colours[8];
-
-    ansi_bright_colours[0] = 0x00555555; // black
-    ansi_bright_colours[1] = 0x00ff5555; // red
-    ansi_bright_colours[2] = 0x0055ff55; // green
-    ansi_bright_colours[3] = 0x00ffff55; // brown
-    ansi_bright_colours[4] = 0x005555ff; // blue
-    ansi_bright_colours[5] = 0x00ff55ff; // magenta
-    ansi_bright_colours[6] = 0x0055ffff; // cyan
-    ansi_bright_colours[7] = 0x00ffffff; // grey
+    cfg->ansi_bright_colours[0] = 0x00555555;
+    cfg->ansi_bright_colours[1] = 0x00ff5555;
+    cfg->ansi_bright_colours[2] = 0x0055ff55;
+    cfg->ansi_bright_colours[3] = 0x00ffff55;
+    cfg->ansi_bright_colours[4] = 0x005555ff;
+    cfg->ansi_bright_colours[5] = 0x00ff55ff;
+    cfg->ansi_bright_colours[6] = 0x0055ffff;
+    cfg->ansi_bright_colours[7] = 0x00ffffff;
 
     char *bright_colours = config_get_value(config, 0, "TERM_PALETTE_BRIGHT");
     if (bright_colours != NULL) {
-        const char *first = bright_colours;
-        size_t i;
-        for (i = 0; i < 8; i++) {
-            const char *last;
-            uint32_t col = strtoui(first, &last, 16);
-            if (first == last)
-                break;
-            ansi_bright_colours[i] = col & 0xffffff;
-            if (*last == 0)
-                break;
-            first = last + 1;
-        }
+        parse_palette(bright_colours, cfg->ansi_bright_colours);
     }
 
-    default_bg = 0x00000000; // background (black)
-    default_fg = 0x00aaaaaa; // foreground (grey)
-
-    default_bg_bright = 0x00555555; // background (black)
-    default_fg_bright = 0x00ffffff; // foreground (grey)
+    default_bg = 0x00000000;
+    default_fg = 0x00aaaaaa;
+    default_bg_bright = 0x00555555;
+    default_fg_bright = 0x00ffffff;
 
-    char *theme_background = config_get_value(config, 0, "TERM_BACKGROUND");
-    if (theme_background != NULL) {
-        default_bg = strtoui(theme_background, NULL, 16);
+    cfg->theme_background = config_get_value(config, 0, "TERM_BACKGROUND");
+    if (cfg->theme_background != NULL) {
+        default_bg = strtoui(cfg->theme_background, NULL, 16);
     }
 
     char *theme_foreground = config_get_value(config, 0, "TERM_FOREGROUND");
@@ -633,11 +589,14 @@ bool gterm_init(struct fb_info **_fbs, size_t *_fbs_count,
         }
     }
 
+    margin = 64;
+    margin_gradient = 4;
+
     if (background == NULL) {
         margin = 0;
         margin_gradient = 0;
     } else {
-        if (theme_background == NULL) {
+        if (cfg->theme_background == NULL) {
             default_bg = 0x80000000;
         }
     }
@@ -656,14 +615,12 @@ bool gterm_init(struct fb_info **_fbs, size_t *_fbs_count,
         margin_gradient = margin;
     }
 
-    size_t font_width = 8;
-    size_t font_height = 16;
-    size_t font_size = (font_width * font_height * FLANTERM_FB_FONT_GLYPHS) / 8;
-
-#define FONT_MAX 16384
-    uint8_t *font = ext_mem_alloc(FONT_MAX);
+    cfg->font_width = 8;
+    cfg->font_height = 16;
+    cfg->font_size = (cfg->font_width * cfg->font_height * FLANTERM_FB_FONT_GLYPHS) / 8;
 
-    memcpy(font, builtin_font, 4096);
+    cfg->font = ext_mem_alloc(FONT_MAX);
+    memcpy(cfg->font, builtin_font, 4096);
 
     size_t tmp_font_width, tmp_font_height;
 
@@ -671,22 +628,22 @@ bool gterm_init(struct fb_info **_fbs, size_t *_fbs_count,
     if (menu_font_size != NULL) {
         if (!parse_resolution(&tmp_font_width, &tmp_font_height, NULL, menu_font_size)) {
             print("Could not parse TERM_FONT_SIZE. Using default font.\n");
-            goto no_load_font;
+            goto config_no_load_font;
         }
 
         if (tmp_font_width != 8) {
             print("Font width must be 8, got %u. Using default font.\n", tmp_font_width);
-            goto no_load_font;
+            goto config_no_load_font;
         }
 
         size_t tmp_font_size = (tmp_font_width * tmp_font_height * FLANTERM_FB_FONT_GLYPHS) / 8;
 
         if (tmp_font_size > FONT_MAX) {
             print("Font would be too large (%U bytes, %u bytes allowed). Not loading.\n", (uint64_t)tmp_font_size, FONT_MAX);
-            goto no_load_font;
+            goto config_no_load_font;
         }
 
-        font_size = tmp_font_size;
+        cfg->font_size = tmp_font_size;
     }
 
     char *menu_font = config_get_value(config, 0, "TERM_FONT");
@@ -695,93 +652,151 @@ bool gterm_init(struct fb_info **_fbs, size_t *_fbs_count,
         if ((f = uri_open(menu_font)) == NULL) {
             print("menu: Could not open font file.\n");
         } else {
-            if (font_size > f->size) {
+            if (cfg->font_size > f->size) {
                 print("Font size too large for provided font file. Not loading.\n");
                 fclose(f);
-                goto no_load_font;
+                goto config_no_load_font;
             }
-            fread(f, font, 0, font_size);
+            fread(f, cfg->font, 0, cfg->font_size);
             if (menu_font_size != NULL) {
-                font_width = tmp_font_width;
-                font_height = tmp_font_height;
+                cfg->font_width = tmp_font_width;
+                cfg->font_height = tmp_font_height;
             }
             fclose(f);
         }
     }
 
-no_load_font:;
-    size_t font_spacing = 1;
+config_no_load_font:;
+    cfg->font_spacing = 1;
     char *font_spacing_str = config_get_value(config, 0, "TERM_FONT_SPACING");
     if (font_spacing_str != NULL) {
-        font_spacing = strtoui(font_spacing_str, NULL, 10);
+        cfg->font_spacing = strtoui(font_spacing_str, NULL, 10);
     }
 
-    size_t font_scale_x = 1;
-    size_t font_scale_y = 1;
-    bool font_scale_is_default = true;
+    cfg->font_scale_x = 1;
+    cfg->font_scale_y = 1;
+    cfg->font_scale_is_default = true;
 
     char *menu_font_scale = config_get_value(config, 0, "TERM_FONT_SCALE");
     if (menu_font_scale != NULL) {
-        parse_resolution(&font_scale_x, &font_scale_y, NULL, menu_font_scale);
-        if (font_scale_x > 8 || font_scale_y > 8) {
-            font_scale_x = 1;
-            font_scale_y = 1;
+        parse_resolution(&cfg->font_scale_x, &cfg->font_scale_y, NULL, menu_font_scale);
+        if (cfg->font_scale_x > 8 || cfg->font_scale_y > 8) {
+            cfg->font_scale_x = 1;
+            cfg->font_scale_y = 1;
+        } else {
+            cfg->font_scale_is_default = false;
+        }
+    }
+}
+
+static void gterm_fb_setup(struct fb_info *fb, char *config,
+                           struct gterm_config *cfg,
+                           size_t *out_scale_x, size_t *out_scale_y) {
+    if (cfg->fb_rotation == FLANTERM_FB_ROTATE_90 || cfg->fb_rotation == FLANTERM_FB_ROTATE_270) {
+        uint64_t tmp = fb->framebuffer_width;
+        fb->framebuffer_width = fb->framebuffer_height;
+        fb->framebuffer_height = tmp;
+    }
+
+    if (background != NULL) {
+        char *background_layout = config_get_value(config, 0, "WALLPAPER_STYLE");
+        if (background_layout != NULL && strcmp(background_layout, "centered") == 0) {
+            char *background_colour = config_get_value(config, 0, "BACKDROP");
+            if (background_colour == NULL)
+                background_colour = "0";
+            uint32_t bg_col = strtoui(background_colour, NULL, 16);
+            image_make_centered(background, fb->framebuffer_width, fb->framebuffer_height, bg_col);
+        } else if (background_layout != NULL && strcmp(background_layout, "tiled") == 0) {
         } else {
-            font_scale_is_default = false;
+            image_make_stretched(background, fb->framebuffer_width, fb->framebuffer_height);
+        }
+    }
+
+    generate_canvas(fb);
+
+    *out_scale_x = cfg->font_scale_x;
+    *out_scale_y = cfg->font_scale_y;
+    if (cfg->font_scale_is_default) {
+        *out_scale_x = 1;
+        *out_scale_y = 1;
+        if (fb->framebuffer_width >= (1920 + 1920 / 3) && fb->framebuffer_height >= (1080 + 1080 / 3)) {
+            *out_scale_x = 2;
+            *out_scale_y = 2;
         }
+        if (fb->framebuffer_width >= (3840 + 3840 / 3) && fb->framebuffer_height >= (2160 + 2160 / 3)) {
+            *out_scale_x = 4;
+            *out_scale_y = 4;
+        }
+    }
+
+    if (cfg->fb_rotation == FLANTERM_FB_ROTATE_90 || cfg->fb_rotation == FLANTERM_FB_ROTATE_270) {
+        uint64_t tmp = fb->framebuffer_width;
+        fb->framebuffer_width = fb->framebuffer_height;
+        fb->framebuffer_height = tmp;
+    }
+}
+
+bool gterm_init(struct fb_info **_fbs, size_t *_fbs_count,
+                char *config, size_t width, size_t height) {
+    static struct fb_info *fbs;
+    static size_t fbs_count;
+
+    static bool prev_valid = false;
+    static char *prev_config;
+    static size_t prev_width, prev_height;
+
+    if (prev_valid && config == prev_config && width == prev_width && height == prev_height) {
+        *_fbs = fbs;
+        *_fbs_count = fbs_count;
+        reset_term();
+        return true;
+    }
+
+    prev_valid = false;
+
+    if (quiet) {
+        term_notready();
+        return false;
+    }
+
+#if defined (UEFI)
+    if (serial || COM_OUTPUT) {
+        term_fallback();
+        return true;
+    }
+#endif
+
+    term_notready();
+
+    // We force bpp to 32
+    fb_init(&fbs, &fbs_count, width, height, 32);
+
+    if (_fbs != NULL) {
+        *_fbs = fbs;
+    }
+    if (_fbs_count != NULL) {
+        *_fbs_count = fbs_count;
     }
 
+    if (fbs_count == 0) {
+        return false;
+    }
+
+    struct gterm_config cfg;
+    gterm_parse_config(config, &cfg);
+
     terms_i = 0;
     terms = ext_mem_alloc(fbs_count * sizeof(void *));
 
     for (size_t i = 0; i < fbs_count; i++) {
         struct fb_info *fb = &fbs[i];
 
-        // Ensure that this framebuffer uses 32-bits per pixel.
         if (fb->framebuffer_bpp != 32) {
             continue;
         }
 
-        if (fb_rotation == FLANTERM_FB_ROTATE_90 || fb_rotation == FLANTERM_FB_ROTATE_270) {
-            uint64_t tmp = fb->framebuffer_width;
-            fb->framebuffer_width = fb->framebuffer_height;
-            fb->framebuffer_height = tmp;
-        }
-
-        if (background != NULL) {
-            char *background_layout = config_get_value(config, 0, "WALLPAPER_STYLE");
-            if (background_layout != NULL && strcmp(background_layout, "centered") == 0) {
-                char *background_colour = config_get_value(config, 0, "BACKDROP");
-                if (background_colour == NULL)
-                    background_colour = "0";
-                uint32_t bg_col = strtoui(background_colour, NULL, 16);
-                image_make_centered(background, fb->framebuffer_width, fb->framebuffer_height, bg_col);
-            } else if (background_layout != NULL && strcmp(background_layout, "tiled") == 0) {
-            } else {
-                image_make_stretched(background, fb->framebuffer_width, fb->framebuffer_height);
-            }
-        }
-
-        generate_canvas(fb);
-
-        if (font_scale_is_default) {
-            font_scale_x = 1;
-            font_scale_y = 1;
-            if (fb->framebuffer_width >= (1920 + 1920 / 3) && fb->framebuffer_height >= (1080 + 1080 / 3)) {
-                font_scale_x = 2;
-                font_scale_y = 2;
-            }
-            if (fb->framebuffer_width >= (3840 + 3840 / 3) && fb->framebuffer_height >= (2160 + 2160 / 3)) {
-                font_scale_x = 4;
-                font_scale_y = 4;
-            }
-        }
-
-        if (fb_rotation == FLANTERM_FB_ROTATE_90 || fb_rotation == FLANTERM_FB_ROTATE_270) {
-            uint64_t tmp = fb->framebuffer_width;
-            fb->framebuffer_width = fb->framebuffer_height;
-            fb->framebuffer_height = tmp;
-        }
+        size_t font_scale_x, font_scale_y;
+        gterm_fb_setup(fb, config, &cfg, &font_scale_x, &font_scale_y);
 
         terms[terms_i] = flanterm_fb_init(ext_mem_alloc_size_t,
                             pmm_free_size_t,
@@ -791,12 +806,12 @@ no_load_font:;
                             fb->green_mask_size, fb->green_mask_shift,
                             fb->blue_mask_size, fb->blue_mask_shift,
                             bg_canvas,
-                            ansi_colours, ansi_bright_colours,
+                            cfg.ansi_colours, cfg.ansi_bright_colours,
                             &default_bg, &default_fg,
                             &default_bg_bright, &default_fg_bright,
-                            font, font_width, font_height, font_spacing,
+                            cfg.font, cfg.font_width, cfg.font_height, cfg.font_spacing,
                             font_scale_x, font_scale_y,
-                            margin, fb_rotation);
+                            margin, cfg.fb_rotation);
 
         if (terms[terms_i] != NULL) {
             terms_i++;
@@ -808,7 +823,7 @@ no_load_font:;
         }
     }
 
-    pmm_free(font, FONT_MAX);
+    pmm_free(cfg.font, FONT_MAX);
 
     if (background != NULL) {
         image_close(background);
@@ -863,3 +878,55 @@ no_load_font:;
 
     return true;
 }
+
+size_t gterm_prepare_flanterm_params(struct fb_info *fbs, size_t fbs_count,
+                                     struct flanterm_params *out, size_t out_max) {
+    struct gterm_config cfg;
+    gterm_parse_config(NULL, &cfg);
+
+    uint32_t configured_default_bg = default_bg;
+
+    size_t count = 0;
+
+    for (size_t i = 0; i < fbs_count && count < out_max; i++) {
+        struct fb_info *fb = &fbs[i];
+
+        if (fb->framebuffer_bpp != 32) {
+            continue;
+        }
+
+        size_t font_scale_x, font_scale_y;
+        gterm_fb_setup(fb, NULL, &cfg, &font_scale_x, &font_scale_y);
+
+        struct flanterm_params *p = &out[count];
+
+        p->canvas = bg_canvas;
+        p->canvas_size = bg_canvas_size;
+        bg_canvas = NULL;
+
+        memcpy(p->ansi_colours, cfg.ansi_colours, sizeof(cfg.ansi_colours));
+        memcpy(p->ansi_bright_colours, cfg.ansi_bright_colours, sizeof(cfg.ansi_bright_colours));
+        p->default_bg = configured_default_bg;
+        p->default_fg = default_fg;
+        p->default_bg_bright = default_bg_bright;
+        p->default_fg_bright = default_fg_bright;
+
+        p->font = cfg.font;
+        p->font_width = cfg.font_width;
+        p->font_height = cfg.font_height;
+        p->font_spacing = cfg.font_spacing;
+        p->font_scale_x = font_scale_x;
+        p->font_scale_y = font_scale_y;
+        p->margin = margin;
+        p->rotation = cfg.fb_rotation;
+
+        count++;
+    }
+
+    if (background != NULL) {
+        image_close(background);
+        background = NULL;
+    }
+
+    return count;
+}
diff --git a/common/lib/gterm.h b/common/lib/gterm.h
index ec579dc4..5f2c4311 100644
--- a/common/lib/gterm.h
+++ b/common/lib/gterm.h
@@ -2,10 +2,33 @@
 #define LIB__GTERM_H__
 
 #include <stddef.h>
+#include <stdint.h>
 #include <stdbool.h>
 #include <lib/fb.h>
 
 bool gterm_init(struct fb_info **ret, size_t *_fbs_count,
                 char *config, size_t width, size_t height);
 
+struct flanterm_params {
+    uint32_t *canvas;
+    size_t canvas_size;
+    uint32_t ansi_colours[8];
+    uint32_t ansi_bright_colours[8];
+    uint32_t default_bg;
+    uint32_t default_fg;
+    uint32_t default_bg_bright;
+    uint32_t default_fg_bright;
+    uint8_t *font;
+    size_t font_width;
+    size_t font_height;
+    size_t font_spacing;
+    size_t font_scale_x;
+    size_t font_scale_y;
+    size_t margin;
+    int rotation;
+};
+
+size_t gterm_prepare_flanterm_params(struct fb_info *fbs, size_t fbs_count,
+                                     struct flanterm_params *out, size_t out_max);
+
 #endif
diff --git a/common/protos/limine.c b/common/protos/limine.c
index 1ff249f3..6344667c 100644
--- a/common/protos/limine.c
+++ b/common/protos/limine.c
@@ -1362,6 +1362,8 @@ FEAT_END
         }
     }
 
+    struct limine_framebuffer *fbp = NULL;
+
     // Framebuffer feature
 FEAT_START
     struct limine_framebuffer_request *framebuffer_request = get_request(LIMINE_FRAMEBUFFER_REQUEST_ID);
@@ -1373,7 +1375,7 @@ FEAT_START
         break;
     }
 
-    struct limine_framebuffer *fbp = ext_mem_alloc(fbs_count * sizeof(struct limine_framebuffer));
+    fbp = ext_mem_alloc(fbs_count * sizeof(struct limine_framebuffer));
 
     struct limine_framebuffer_response *framebuffer_response =
         ext_mem_alloc(sizeof(struct limine_framebuffer_response));
@@ -1418,6 +1420,63 @@ FEAT_START
     framebuffer_request->response = reported_addr(framebuffer_response);
 FEAT_END
 
+    // Flanterm FB init params feature
+FEAT_START
+    struct limine_flanterm_fb_init_params_request *fip_request = get_request(LIMINE_FLANTERM_FB_INIT_PARAMS_REQUEST_ID);
+    if (fip_request == NULL) {
+        break;
+    }
+
+    if (fbp == NULL || fbs_count == 0) {
+        break;
+    }
+
+    struct flanterm_params *fip_raw = ext_mem_alloc(fbs_count * sizeof(struct flanterm_params));
+    size_t fip_count = gterm_prepare_flanterm_params(fbs, fbs_count, fip_raw, fbs_count);
+
+    struct limine_flanterm_fb_init_params *fip_entries =
+        ext_mem_alloc(fbs_count * sizeof(struct limine_flanterm_fb_init_params));
+    uint64_t *fip_list = ext_mem_alloc(fbs_count * sizeof(uint64_t));
+
+    size_t fip_idx = 0;
+    for (size_t i = 0; i < fbs_count; i++) {
+        struct limine_flanterm_fb_init_params *entry = &fip_entries[i];
+
+        if (fbs[i].framebuffer_bpp == 32 && fip_idx < fip_count) {
+            struct flanterm_params *raw = &fip_raw[fip_idx];
+
+            entry->canvas = raw->canvas != NULL ? reported_addr(raw->canvas) : 0;
+            entry->canvas_size = raw->canvas_size;
+            memcpy(entry->ansi_colours, raw->ansi_colours, sizeof(raw->ansi_colours));
+            memcpy(entry->ansi_bright_colours, raw->ansi_bright_colours, sizeof(raw->ansi_bright_colours));
+            entry->default_bg = raw->default_bg;
+            entry->default_fg = raw->default_fg;
+            entry->default_bg_bright = raw->default_bg_bright;
+            entry->default_fg_bright = raw->default_fg_bright;
+            entry->font = reported_addr(raw->font);
+            entry->font_width = raw->font_width;
+            entry->font_height = raw->font_height;
+            entry->font_spacing = raw->font_spacing;
+            entry->font_scale_x = raw->font_scale_x;
+            entry->font_scale_y = raw->font_scale_y;
+            entry->margin = raw->margin;
+            entry->rotation = raw->rotation;
+
+            fip_idx++;
+        }
+
+        fip_list[i] = reported_addr(entry);
+    }
+
+    struct limine_flanterm_fb_init_params_response *fip_response =
+        ext_mem_alloc(sizeof(struct limine_flanterm_fb_init_params_response));
+
+    fip_response->entry_count = fbs_count;
+    fip_response->entries = reported_addr(fip_list);
+
+    fip_request->response = reported_addr(fip_response);
+FEAT_END
+
 no_fb:
     // Boot time feature
 FEAT_START
tab: 248 wrap: offon