On Mon, 13 Jun 2016 at 12:35:23 +0200, Mark Kettenis wrote:
> > Date: Sun, 12 Jun 2016 11:47:37 -0500
> > From: joshua stein <[email protected]>
> > 
> > Here's a new version with feedback from Miod and Ted.
> > 
> > It also fixes a bug on a Broadwell Chromebook (tested by Edward
> > Wandasiewicz) which has proper inteldrm but no vga, so cbfb was
> > getting chosen as the console early on but then not detaching when
> > inteldrm wanted to take over.  This detaches cbfb in the intel and
> > radeon drivers.
> 
> The addition of those hooks makes me even more convinced that efifb(4)
> and cbfb(4) should be the same driver.  The only thing that is really
> different is the data structure that is used to initialize the
> framebuffer parameters.
> 
> We should not get hung up too much about the driver name.  If it is
> felt that efifb(4) is inappropriate for these chromebooks with
> coreboot, we can always rename the driver.

Here is a third version that just integrates the coreboot code into
efifb.  The cnattach path still has to be different to allow vga to
try to attach before doing the coreboot version.


Index: arch/amd64/amd64/efifb.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/amd64/efifb.c,v
retrieving revision 1.8
diff -u -p -u -p -r1.8 efifb.c
--- arch/amd64/amd64/efifb.c    1 Dec 2015 18:42:56 -0000       1.8
+++ arch/amd64/amd64/efifb.c    16 Jun 2016 16:28:29 -0000
@@ -2,6 +2,7 @@
 
 /*
  * Copyright (c) 2015 YASUOKA Masahiko <[email protected]>
+ * Copyright (c) 2016 joshua stein <[email protected]>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -30,11 +31,56 @@
 #include <machine/biosvar.h>
 #include <machine/efifbvar.h>
 
+/* coreboot tables */
+
+struct cb_header {
+       union {
+               uint8_t signature[4]; /* "LBIO" */
+               uint32_t signature32;
+       };
+       uint32_t        header_bytes;
+       uint32_t        header_checksum;
+       uint32_t        table_bytes;
+       uint32_t        table_checksum;
+       uint32_t        table_entries;
+};
+
+struct cb_framebuffer {
+       uint64_t        physical_address;
+       uint32_t        x_resolution;
+       uint32_t        y_resolution;
+       uint32_t        bytes_per_line;
+       uint8_t         bits_per_pixel;
+       uint8_t         red_mask_pos;
+       uint8_t         red_mask_size;
+       uint8_t         green_mask_pos;
+       uint8_t         green_mask_size;
+       uint8_t         blue_mask_pos;
+       uint8_t         blue_mask_size;
+       uint8_t         reserved_mask_pos;
+       uint8_t         reserved_mask_size;
+};
+
+struct cb_entry {
+       uint32_t        tag;
+#define CB_TAG_VERSION          0x0004
+#define CB_TAG_FORWARD          0x0011
+#define CB_TAG_FRAMEBUFFER      0x0012
+       uint32_t        size;
+       union {
+               char    string[0];
+               uint64_t forward;
+               struct cb_framebuffer fb;
+       } u;
+};
+
 struct efifb {
        struct rasops_info       rinfo;
        int                      depth;
        paddr_t                  paddr;
        psize_t                  psize;
+
+       struct cb_framebuffer    cb_table_fb;
 };
 
 struct efifb_softc {
@@ -45,6 +91,7 @@ struct efifb_softc {
 int     efifb_match(struct device *, void *, void *);
 void    efifb_attach(struct device *, struct device *, void *);
 void    efifb_rasops_preinit(struct efifb *);
+void    efifb_rasops_init(void);
 int     efifb_ioctl(void *, u_long, caddr_t, int, struct proc *);
 paddr_t         efifb_mmap(void *, off_t, int);
 int     efifb_alloc_screen(void *, const struct wsscreen_descr *, void **,
@@ -55,6 +102,8 @@ int   efifb_show_screen(void *, void *, i
 int     efifb_list_font(void *, struct wsdisplay_font *);
 int     efifb_load_font(void *, void *, struct wsdisplay_font *);
 
+struct cb_framebuffer * cb_find_fb(paddr_t);
+
 struct cfattach efifb_ca = {
        sizeof(struct efifb_softc), efifb_match, efifb_attach, NULL
 };
@@ -112,7 +161,8 @@ efifb_attach(struct device *parent, stru
        bus_space_handle_t       ioh;
        long                     defattr;
 
-       printf("\n");
+       printf(": %dx%d, %dbpp\n", efifb_console.rinfo.ri_width,
+           efifb_console.rinfo.ri_height, efifb_console.rinfo.ri_depth);
 
        if (1) {        /* XXX console */
                aa.console = 1;
@@ -151,16 +201,29 @@ efifb_rasops_preinit(struct efifb *fb)
 #define bmpos(_x) (ffs(_x) - 1)
        struct rasops_info      *ri = &fb->rinfo;
 
-       ri->ri_width = bios_efiinfo->fb_width;
-       ri->ri_height = bios_efiinfo->fb_height;
-       ri->ri_depth = fb->depth;
-       ri->ri_stride = bios_efiinfo->fb_pixpsl * (fb->depth / 8);
-       ri->ri_rnum = bmnum(bios_efiinfo->fb_red_mask);
-       ri->ri_rpos = bmpos(bios_efiinfo->fb_red_mask);
-       ri->ri_gnum = bmnum(bios_efiinfo->fb_green_mask);
-       ri->ri_gpos = bmpos(bios_efiinfo->fb_green_mask);
-       ri->ri_bnum = bmnum(bios_efiinfo->fb_blue_mask);
-       ri->ri_bpos = bmpos(bios_efiinfo->fb_blue_mask);
+       if (efifb_console.cb_table_fb.x_resolution) {
+               ri->ri_width = efifb_console.cb_table_fb.x_resolution;
+               ri->ri_height = efifb_console.cb_table_fb.y_resolution;
+               ri->ri_depth = fb->depth;
+               ri->ri_stride = efifb_console.cb_table_fb.bytes_per_line;
+               ri->ri_rnum = efifb_console.cb_table_fb.red_mask_size;
+               ri->ri_rpos = efifb_console.cb_table_fb.red_mask_pos;
+               ri->ri_gnum = efifb_console.cb_table_fb.green_mask_size;
+               ri->ri_gpos = efifb_console.cb_table_fb.green_mask_pos;
+               ri->ri_bnum = efifb_console.cb_table_fb.blue_mask_size;
+               ri->ri_bpos = efifb_console.cb_table_fb.blue_mask_pos;
+       } else {
+               ri->ri_width = bios_efiinfo->fb_width;
+               ri->ri_height = bios_efiinfo->fb_height;
+               ri->ri_depth = fb->depth;
+               ri->ri_stride = bios_efiinfo->fb_pixpsl * (fb->depth / 8);
+               ri->ri_rnum = bmnum(bios_efiinfo->fb_red_mask);
+               ri->ri_rpos = bmpos(bios_efiinfo->fb_red_mask);
+               ri->ri_gnum = bmnum(bios_efiinfo->fb_green_mask);
+               ri->ri_gpos = bmpos(bios_efiinfo->fb_green_mask);
+               ri->ri_bnum = bmnum(bios_efiinfo->fb_blue_mask);
+               ri->ri_bpos = bmpos(bios_efiinfo->fb_blue_mask);
+       }
 }
 
 int
@@ -285,8 +348,6 @@ int
 efifb_cnattach(void)
 {
        struct efifb            *fb = &efifb_console;
-       struct rasops_info      *ri = &fb->rinfo;
-       long                     defattr = 0;
 
        if (bios_efiinfo == NULL || bios_efiinfo->fb_addr == 0)
                return (-1);
@@ -302,22 +363,7 @@ efifb_cnattach(void)
        fb->psize = bios_efiinfo->fb_height *
            bios_efiinfo->fb_pixpsl * (fb->depth / 8);
 
-       ri->ri_bits = (u_char *)PMAP_DIRECT_MAP(fb->paddr);
-
-       efifb_rasops_preinit(fb);
-
-       ri->ri_bs = efifb_bs;
-       ri->ri_flg = RI_CLEAR | RI_CENTER | RI_WRONLY;
-       rasops_init(ri, EFIFB_HEIGHT, EFIFB_WIDTH);
-       efifb_std_descr.ncols = ri->ri_cols;
-       efifb_std_descr.nrows = ri->ri_rows;
-       efifb_std_descr.textops = &ri->ri_ops;
-       efifb_std_descr.fontwidth = ri->ri_font->fontwidth;
-       efifb_std_descr.fontheight = ri->ri_font->fontheight;
-       efifb_std_descr.capabilities = ri->ri_caps;
-
-       ri->ri_ops.alloc_attr(ri, 0, 0, 0, &defattr);
-       wsdisplay_cnattach(&efifb_std_descr, ri, 0, 0, defattr);
+       efifb_rasops_init();
 
        return (0);
 }
@@ -357,4 +403,111 @@ void
 efifb_cndetach(void)
 {
        efifb_console.paddr = 0;
+}
+
+void
+efifb_rasops_init(void)
+{
+       struct efifb            *fb = &efifb_console;
+       struct rasops_info      *ri = &fb->rinfo;
+       long                     defattr = 0;
+
+       ri->ri_bits = (u_char *)PMAP_DIRECT_MAP(fb->paddr);
+
+       efifb_rasops_preinit(fb);
+
+       ri->ri_bs = efifb_bs;
+       ri->ri_flg = RI_CLEAR | RI_CENTER | RI_WRONLY;
+       rasops_init(ri, EFIFB_HEIGHT, EFIFB_WIDTH);
+       efifb_std_descr.ncols = ri->ri_cols;
+       efifb_std_descr.nrows = ri->ri_rows;
+       efifb_std_descr.textops = &ri->ri_ops;
+       efifb_std_descr.fontwidth = ri->ri_font->fontwidth;
+       efifb_std_descr.fontheight = ri->ri_font->fontheight;
+       efifb_std_descr.capabilities = ri->ri_caps;
+
+       ri->ri_ops.alloc_attr(ri, 0, 0, 0, &defattr);
+       wsdisplay_cnattach(&efifb_std_descr, ri, 0, 0, defattr);
+}
+
+int
+efifb_cb_cnattach(void)
+{
+       struct cb_framebuffer *cb_fb = cb_find_fb((paddr_t)0x0);
+
+       if (cb_fb == NULL || !cb_fb->x_resolution)
+               return (-1);
+
+       memset(&efifb_console, 0, sizeof(efifb_console));
+       memcpy(&efifb_console.cb_table_fb, cb_fb,
+           sizeof(struct cb_framebuffer));
+
+       efifb_console.paddr = cb_fb->physical_address;
+       efifb_console.depth = cb_fb->bits_per_pixel;
+       efifb_console.psize = cb_fb->y_resolution * cb_fb->bytes_per_line;
+
+       efifb_rasops_init();
+
+       return (0);
+}
+
+int
+efifb_cb_found(void)
+{
+       return (efifb_console.paddr && efifb_console.cb_table_fb.x_resolution);
+}
+
+static uint16_t
+cb_checksum(const void *addr, unsigned size)
+{
+       const uint16_t *p = addr;
+       unsigned i, n = size / 2;
+       uint32_t sum = 0;
+
+       for (i = 0; i < n; i++)
+               sum += p[i];
+
+       sum = (sum >> 16) + (sum & 0xffff);
+       sum += (sum >> 16);
+       sum = ~sum & 0xffff;
+
+       return (uint16_t)sum;
+}
+
+struct cb_framebuffer *
+cb_find_fb(paddr_t addr)
+{
+       int i, j;
+
+       for (i = 0; i < (4 * 1024); i += 16) {
+               struct cb_header *cbh;
+               struct cb_entry *cbe;
+               paddr_t cbtable;
+
+               cbh = (struct cb_header *)(PMAP_DIRECT_MAP(addr + i));
+               if (memcmp(cbh->signature, "LBIO", 4) != 0)
+                       continue;
+
+               if (!cbh->header_bytes)
+                       continue;
+
+               if (cb_checksum(cbh, sizeof(*cbh)) != 0)
+                       return NULL;
+
+               cbtable = PMAP_DIRECT_MAP(addr + i + cbh->header_bytes);
+
+               for (j = 0; j < cbh->table_bytes; j += cbe->size) {
+                       cbe = (struct cb_entry *)((char *)cbtable + j);
+
+                       switch (cbe->tag) {
+                       case CB_TAG_FORWARD:
+                               return cb_find_fb(cbe->u.forward);
+
+                       case CB_TAG_FRAMEBUFFER:
+                               return &cbe->u.fb;
+                       }
+               }
+       }
+
+       return NULL;
 }
Index: arch/amd64/amd64/mainbus.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/amd64/mainbus.c,v
retrieving revision 1.36
diff -u -p -u -p -r1.36 mainbus.c
--- arch/amd64/amd64/mainbus.c  12 Dec 2015 12:33:49 -0000      1.36
+++ arch/amd64/amd64/mainbus.c  16 Jun 2016 16:28:29 -0000
@@ -253,7 +253,7 @@ mainbus_attach(struct device *parent, st
 #endif /* NVMM > 0 */
 
 #if NEFIFB > 0
-       if (bios_efiinfo != NULL) {
+       if (bios_efiinfo != NULL || efifb_cb_found()) {
                mba.mba_eaa.eaa_name = "efifb";
                config_found(self, &mba, mainbus_print);
        }
Index: arch/amd64/amd64/wscons_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/amd64/wscons_machdep.c,v
retrieving revision 1.12
diff -u -p -u -p -r1.12 wscons_machdep.c
--- arch/amd64/amd64/wscons_machdep.c   6 Mar 2016 22:41:24 -0000       1.12
+++ arch/amd64/amd64/wscons_machdep.c   16 Jun 2016 16:28:29 -0000
@@ -147,6 +147,10 @@ wscn_video_init(void)
        if (vga_cnattach(X86_BUS_SPACE_IO, X86_BUS_SPACE_MEM, -1, 1) == 0)
                return (0);
 #endif
+#if (NEFIFB > 0)
+       if (efifb_cb_cnattach() == 0)
+               return (0);
+#endif
 #if (NPCDISPLAY > 0)
        if (pcdisplay_cnattach(X86_BUS_SPACE_IO, X86_BUS_SPACE_MEM) == 0)
                return (0);
Index: arch/amd64/include/efifbvar.h
===================================================================
RCS file: /cvs/src/sys/arch/amd64/include/efifbvar.h,v
retrieving revision 1.3
diff -u -p -u -p -r1.3 efifbvar.h
--- arch/amd64/include/efifbvar.h       30 Oct 2015 11:21:01 -0000      1.3
+++ arch/amd64/include/efifbvar.h       16 Jun 2016 16:28:29 -0000
@@ -29,4 +29,7 @@ int efifb_cnattach(void);
 int efifb_is_console(struct pci_attach_args *);
 void efifb_cndetach(void);
 
+int efifb_cb_found(void);
+int efifb_cb_cnattach(void);
+
 #endif /* _MACHINE_EFIFB_H_ */

Reply via email to