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_ */
