linux/drivers/video/fbdev/efifb.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Framebuffer driver for EFI/UEFI based system
   4 *
   5 * (c) 2006 Edgar Hucek <gimli@dark-green.com>
   6 * Original efi driver written by Gerd Knorr <kraxel@goldbach.in-berlin.de>
   7 *
   8 */
   9
  10#include <linux/kernel.h>
  11#include <linux/efi.h>
  12#include <linux/efi-bgrt.h>
  13#include <linux/errno.h>
  14#include <linux/fb.h>
  15#include <linux/pci.h>
  16#include <linux/platform_device.h>
  17#include <linux/printk.h>
  18#include <linux/screen_info.h>
  19#include <linux/pm_runtime.h>
  20#include <video/vga.h>
  21#include <asm/efi.h>
  22#include <drm/drm_utils.h> /* For drm_get_panel_orientation_quirk */
  23#include <drm/drm_connector.h>  /* For DRM_MODE_PANEL_ORIENTATION_* */
  24
  25struct bmp_file_header {
  26        u16 id;
  27        u32 file_size;
  28        u32 reserved;
  29        u32 bitmap_offset;
  30} __packed;
  31
  32struct bmp_dib_header {
  33        u32 dib_header_size;
  34        s32 width;
  35        s32 height;
  36        u16 planes;
  37        u16 bpp;
  38        u32 compression;
  39        u32 bitmap_size;
  40        u32 horz_resolution;
  41        u32 vert_resolution;
  42        u32 colors_used;
  43        u32 colors_important;
  44} __packed;
  45
  46static bool use_bgrt = true;
  47static bool request_mem_succeeded = false;
  48static u64 mem_flags = EFI_MEMORY_WC | EFI_MEMORY_UC;
  49
  50static struct pci_dev *efifb_pci_dev;   /* dev with BAR covering the efifb */
  51
  52static struct fb_var_screeninfo efifb_defined = {
  53        .activate               = FB_ACTIVATE_NOW,
  54        .height                 = -1,
  55        .width                  = -1,
  56        .right_margin           = 32,
  57        .upper_margin           = 16,
  58        .lower_margin           = 4,
  59        .vsync_len              = 4,
  60        .vmode                  = FB_VMODE_NONINTERLACED,
  61};
  62
  63static struct fb_fix_screeninfo efifb_fix = {
  64        .id                     = "EFI VGA",
  65        .type                   = FB_TYPE_PACKED_PIXELS,
  66        .accel                  = FB_ACCEL_NONE,
  67        .visual                 = FB_VISUAL_TRUECOLOR,
  68};
  69
  70static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green,
  71                           unsigned blue, unsigned transp,
  72                           struct fb_info *info)
  73{
  74        /*
  75         *  Set a single color register. The values supplied are
  76         *  already rounded down to the hardware's capabilities
  77         *  (according to the entries in the `var' structure). Return
  78         *  != 0 for invalid regno.
  79         */
  80
  81        if (regno >= info->cmap.len)
  82                return 1;
  83
  84        if (regno < 16) {
  85                red   >>= 16 - info->var.red.length;
  86                green >>= 16 - info->var.green.length;
  87                blue  >>= 16 - info->var.blue.length;
  88                ((u32 *)(info->pseudo_palette))[regno] =
  89                        (red   << info->var.red.offset)   |
  90                        (green << info->var.green.offset) |
  91                        (blue  << info->var.blue.offset);
  92        }
  93        return 0;
  94}
  95
  96/*
  97 * If fbcon deffered console takeover is configured, the intent is for the
  98 * framebuffer to show the boot graphics (e.g. vendor logo) until there is some
  99 * (error) message to display. But the boot graphics may have been destroyed by
 100 * e.g. option ROM output, detect this and restore the boot graphics.
 101 */
 102#if defined CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER && \
 103    defined CONFIG_ACPI_BGRT
 104static void efifb_copy_bmp(u8 *src, u32 *dst, int width, struct screen_info *si)
 105{
 106        u8 r, g, b;
 107
 108        while (width--) {
 109                b = *src++;
 110                g = *src++;
 111                r = *src++;
 112                *dst++ = (r << si->red_pos)   |
 113                         (g << si->green_pos) |
 114                         (b << si->blue_pos);
 115        }
 116}
 117
 118#ifdef CONFIG_X86
 119/*
 120 * On x86 some firmwares use a low non native resolution for the display when
 121 * they have shown some text messages. While keeping the bgrt filled with info
 122 * for the native resolution. If the bgrt image intended for the native
 123 * resolution still fits, it will be displayed very close to the right edge of
 124 * the display looking quite bad. This function checks for this.
 125 */
 126static bool efifb_bgrt_sanity_check(struct screen_info *si, u32 bmp_width)
 127{
 128        /*
 129         * All x86 firmwares horizontally center the image (the yoffset
 130         * calculations differ between boards, but xoffset is predictable).
 131         */
 132        u32 expected_xoffset = (si->lfb_width - bmp_width) / 2;
 133
 134        return bgrt_tab.image_offset_x == expected_xoffset;
 135}
 136#else
 137static bool efifb_bgrt_sanity_check(struct screen_info *si, u32 bmp_width)
 138{
 139        return true;
 140}
 141#endif
 142
 143static void efifb_show_boot_graphics(struct fb_info *info)
 144{
 145        u32 bmp_width, bmp_height, bmp_pitch, dst_x, y, src_y;
 146        struct screen_info *si = &screen_info;
 147        struct bmp_file_header *file_header;
 148        struct bmp_dib_header *dib_header;
 149        void *bgrt_image = NULL;
 150        u8 *dst = info->screen_base;
 151
 152        if (!use_bgrt)
 153                return;
 154
 155        if (!bgrt_tab.image_address) {
 156                pr_info("efifb: No BGRT, not showing boot graphics\n");
 157                return;
 158        }
 159
 160        if (bgrt_tab.status & 0x06) {
 161                pr_info("efifb: BGRT rotation bits set, not showing boot graphics\n");
 162                return;
 163        }
 164
 165        /* Avoid flashing the logo if we're going to print std probe messages */
 166        if (console_loglevel > CONSOLE_LOGLEVEL_QUIET)
 167                return;
 168
 169        /* bgrt_tab.status is unreliable, so we don't check it */
 170
 171        if (si->lfb_depth != 32) {
 172                pr_info("efifb: not 32 bits, not showing boot graphics\n");
 173                return;
 174        }
 175
 176        bgrt_image = memremap(bgrt_tab.image_address, bgrt_image_size,
 177                              MEMREMAP_WB);
 178        if (!bgrt_image) {
 179                pr_warn("efifb: Ignoring BGRT: failed to map image memory\n");
 180                return;
 181        }
 182
 183        if (bgrt_image_size < (sizeof(*file_header) + sizeof(*dib_header)))
 184                goto error;
 185
 186        file_header = bgrt_image;
 187        if (file_header->id != 0x4d42 || file_header->reserved != 0)
 188                goto error;
 189
 190        dib_header = bgrt_image + sizeof(*file_header);
 191        if (dib_header->dib_header_size != 40 || dib_header->width < 0 ||
 192            dib_header->planes != 1 || dib_header->bpp != 24 ||
 193            dib_header->compression != 0)
 194                goto error;
 195
 196        bmp_width = dib_header->width;
 197        bmp_height = abs(dib_header->height);
 198        bmp_pitch = round_up(3 * bmp_width, 4);
 199
 200        if ((file_header->bitmap_offset + bmp_pitch * bmp_height) >
 201                                bgrt_image_size)
 202                goto error;
 203
 204        if ((bgrt_tab.image_offset_x + bmp_width) > si->lfb_width ||
 205            (bgrt_tab.image_offset_y + bmp_height) > si->lfb_height)
 206                goto error;
 207
 208        if (!efifb_bgrt_sanity_check(si, bmp_width))
 209                goto error;
 210
 211        pr_info("efifb: showing boot graphics\n");
 212
 213        for (y = 0; y < si->lfb_height; y++, dst += si->lfb_linelength) {
 214                /* Only background? */
 215                if (y < bgrt_tab.image_offset_y ||
 216                    y >= (bgrt_tab.image_offset_y + bmp_height)) {
 217                        memset(dst, 0, 4 * si->lfb_width);
 218                        continue;
 219                }
 220
 221                src_y = y - bgrt_tab.image_offset_y;
 222                /* Positive header height means upside down row order */
 223                if (dib_header->height > 0)
 224                        src_y = (bmp_height - 1) - src_y;
 225
 226                memset(dst, 0, bgrt_tab.image_offset_x * 4);
 227                dst_x = bgrt_tab.image_offset_x;
 228                efifb_copy_bmp(bgrt_image + file_header->bitmap_offset +
 229                                            src_y * bmp_pitch,
 230                               (u32 *)dst + dst_x, bmp_width, si);
 231                dst_x += bmp_width;
 232                memset((u32 *)dst + dst_x, 0, (si->lfb_width - dst_x) * 4);
 233        }
 234
 235        memunmap(bgrt_image);
 236        return;
 237
 238error:
 239        memunmap(bgrt_image);
 240        pr_warn("efifb: Ignoring BGRT: unexpected or invalid BMP data\n");
 241}
 242#else
 243static inline void efifb_show_boot_graphics(struct fb_info *info) {}
 244#endif
 245
 246/*
 247 * fb_ops.fb_destroy is called by the last put_fb_info() call at the end
 248 * of unregister_framebuffer() or fb_release(). Do any cleanup here.
 249 */
 250static void efifb_destroy(struct fb_info *info)
 251{
 252        if (efifb_pci_dev)
 253                pm_runtime_put(&efifb_pci_dev->dev);
 254
 255        if (info->screen_base) {
 256                if (mem_flags & (EFI_MEMORY_UC | EFI_MEMORY_WC))
 257                        iounmap(info->screen_base);
 258                else
 259                        memunmap(info->screen_base);
 260        }
 261
 262        if (request_mem_succeeded)
 263                release_mem_region(info->apertures->ranges[0].base,
 264                                   info->apertures->ranges[0].size);
 265        fb_dealloc_cmap(&info->cmap);
 266
 267        framebuffer_release(info);
 268}
 269
 270static const struct fb_ops efifb_ops = {
 271        .owner          = THIS_MODULE,
 272        .fb_destroy     = efifb_destroy,
 273        .fb_setcolreg   = efifb_setcolreg,
 274        .fb_fillrect    = cfb_fillrect,
 275        .fb_copyarea    = cfb_copyarea,
 276        .fb_imageblit   = cfb_imageblit,
 277};
 278
 279static int efifb_setup(char *options)
 280{
 281        char *this_opt;
 282
 283        if (options && *options) {
 284                while ((this_opt = strsep(&options, ",")) != NULL) {
 285                        if (!*this_opt) continue;
 286
 287                        efifb_setup_from_dmi(&screen_info, this_opt);
 288
 289                        if (!strncmp(this_opt, "base:", 5))
 290                                screen_info.lfb_base = simple_strtoul(this_opt+5, NULL, 0);
 291                        else if (!strncmp(this_opt, "stride:", 7))
 292                                screen_info.lfb_linelength = simple_strtoul(this_opt+7, NULL, 0) * 4;
 293                        else if (!strncmp(this_opt, "height:", 7))
 294                                screen_info.lfb_height = simple_strtoul(this_opt+7, NULL, 0);
 295                        else if (!strncmp(this_opt, "width:", 6))
 296                                screen_info.lfb_width = simple_strtoul(this_opt+6, NULL, 0);
 297                        else if (!strcmp(this_opt, "nowc"))
 298                                mem_flags &= ~EFI_MEMORY_WC;
 299                        else if (!strcmp(this_opt, "nobgrt"))
 300                                use_bgrt = false;
 301                }
 302        }
 303
 304        return 0;
 305}
 306
 307static inline bool fb_base_is_valid(void)
 308{
 309        if (screen_info.lfb_base)
 310                return true;
 311
 312        if (!(screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE))
 313                return false;
 314
 315        if (screen_info.ext_lfb_base)
 316                return true;
 317
 318        return false;
 319}
 320
 321#define efifb_attr_decl(name, fmt)                                      \
 322static ssize_t name##_show(struct device *dev,                          \
 323                           struct device_attribute *attr,               \
 324                           char *buf)                                   \
 325{                                                                       \
 326        return sprintf(buf, fmt "\n", (screen_info.lfb_##name));        \
 327}                                                                       \
 328static DEVICE_ATTR_RO(name)
 329
 330efifb_attr_decl(base, "0x%x");
 331efifb_attr_decl(linelength, "%u");
 332efifb_attr_decl(height, "%u");
 333efifb_attr_decl(width, "%u");
 334efifb_attr_decl(depth, "%u");
 335
 336static struct attribute *efifb_attrs[] = {
 337        &dev_attr_base.attr,
 338        &dev_attr_linelength.attr,
 339        &dev_attr_width.attr,
 340        &dev_attr_height.attr,
 341        &dev_attr_depth.attr,
 342        NULL
 343};
 344ATTRIBUTE_GROUPS(efifb);
 345
 346static bool pci_dev_disabled;   /* FB base matches BAR of a disabled device */
 347
 348static struct resource *bar_resource;
 349static u64 bar_offset;
 350
 351static int efifb_probe(struct platform_device *dev)
 352{
 353        struct fb_info *info;
 354        int err, orientation;
 355        unsigned int size_vmode;
 356        unsigned int size_remap;
 357        unsigned int size_total;
 358        char *option = NULL;
 359        efi_memory_desc_t md;
 360
 361        /*
 362         * Generic drivers must not be registered if a framebuffer exists.
 363         * If a native driver was probed, the display hardware was already
 364         * taken and attempting to use the system framebuffer is dangerous.
 365         */
 366        if (num_registered_fb > 0) {
 367                dev_err(&dev->dev,
 368                        "efifb: a framebuffer is already registered\n");
 369                return -EINVAL;
 370        }
 371
 372        if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI || pci_dev_disabled)
 373                return -ENODEV;
 374
 375        if (fb_get_options("efifb", &option))
 376                return -ENODEV;
 377        efifb_setup(option);
 378
 379        /* We don't get linelength from UGA Draw Protocol, only from
 380         * EFI Graphics Protocol.  So if it's not in DMI, and it's not
 381         * passed in from the user, we really can't use the framebuffer.
 382         */
 383        if (!screen_info.lfb_linelength)
 384                return -ENODEV;
 385
 386        if (!screen_info.lfb_depth)
 387                screen_info.lfb_depth = 32;
 388        if (!screen_info.pages)
 389                screen_info.pages = 1;
 390        if (!fb_base_is_valid()) {
 391                printk(KERN_DEBUG "efifb: invalid framebuffer address\n");
 392                return -ENODEV;
 393        }
 394        printk(KERN_INFO "efifb: probing for efifb\n");
 395
 396        /* just assume they're all unset if any are */
 397        if (!screen_info.blue_size) {
 398                screen_info.blue_size = 8;
 399                screen_info.blue_pos = 0;
 400                screen_info.green_size = 8;
 401                screen_info.green_pos = 8;
 402                screen_info.red_size = 8;
 403                screen_info.red_pos = 16;
 404                screen_info.rsvd_size = 8;
 405                screen_info.rsvd_pos = 24;
 406        }
 407
 408        efifb_fix.smem_start = screen_info.lfb_base;
 409
 410        if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE) {
 411                u64 ext_lfb_base;
 412
 413                ext_lfb_base = (u64)(unsigned long)screen_info.ext_lfb_base << 32;
 414                efifb_fix.smem_start |= ext_lfb_base;
 415        }
 416
 417        if (bar_resource &&
 418            bar_resource->start + bar_offset != efifb_fix.smem_start) {
 419                dev_info(&efifb_pci_dev->dev,
 420                         "BAR has moved, updating efifb address\n");
 421                efifb_fix.smem_start = bar_resource->start + bar_offset;
 422        }
 423
 424        efifb_defined.bits_per_pixel = screen_info.lfb_depth;
 425        efifb_defined.xres = screen_info.lfb_width;
 426        efifb_defined.yres = screen_info.lfb_height;
 427        efifb_fix.line_length = screen_info.lfb_linelength;
 428
 429        /*   size_vmode -- that is the amount of memory needed for the
 430         *                 used video mode, i.e. the minimum amount of
 431         *                 memory we need. */
 432        size_vmode = efifb_defined.yres * efifb_fix.line_length;
 433
 434        /*   size_total -- all video memory we have. Used for
 435         *                 entries, ressource allocation and bounds
 436         *                 checking. */
 437        size_total = screen_info.lfb_size;
 438        if (size_total < size_vmode)
 439                size_total = size_vmode;
 440
 441        /*   size_remap -- the amount of video memory we are going to
 442         *                 use for efifb.  With modern cards it is no
 443         *                 option to simply use size_total as that
 444         *                 wastes plenty of kernel address space. */
 445        size_remap  = size_vmode * 2;
 446        if (size_remap > size_total)
 447                size_remap = size_total;
 448        if (size_remap % PAGE_SIZE)
 449                size_remap += PAGE_SIZE - (size_remap % PAGE_SIZE);
 450        efifb_fix.smem_len = size_remap;
 451
 452        if (request_mem_region(efifb_fix.smem_start, size_remap, "efifb")) {
 453                request_mem_succeeded = true;
 454        } else {
 455                /* We cannot make this fatal. Sometimes this comes from magic
 456                   spaces our resource handlers simply don't know about */
 457                pr_warn("efifb: cannot reserve video memory at 0x%lx\n",
 458                        efifb_fix.smem_start);
 459        }
 460
 461        info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
 462        if (!info) {
 463                err = -ENOMEM;
 464                goto err_release_mem;
 465        }
 466        platform_set_drvdata(dev, info);
 467        info->pseudo_palette = info->par;
 468        info->par = NULL;
 469
 470        info->apertures = alloc_apertures(1);
 471        if (!info->apertures) {
 472                err = -ENOMEM;
 473                goto err_release_fb;
 474        }
 475        info->apertures->ranges[0].base = efifb_fix.smem_start;
 476        info->apertures->ranges[0].size = size_remap;
 477
 478        if (efi_enabled(EFI_MEMMAP) &&
 479            !efi_mem_desc_lookup(efifb_fix.smem_start, &md)) {
 480                if ((efifb_fix.smem_start + efifb_fix.smem_len) >
 481                    (md.phys_addr + (md.num_pages << EFI_PAGE_SHIFT))) {
 482                        pr_err("efifb: video memory @ 0x%lx spans multiple EFI memory regions\n",
 483                               efifb_fix.smem_start);
 484                        err = -EIO;
 485                        goto err_release_fb;
 486                }
 487                /*
 488                 * If the UEFI memory map covers the efifb region, we may only
 489                 * remap it using the attributes the memory map prescribes.
 490                 */
 491                md.attribute &= EFI_MEMORY_UC | EFI_MEMORY_WC |
 492                                EFI_MEMORY_WT | EFI_MEMORY_WB;
 493                if (md.attribute) {
 494                        mem_flags |= EFI_MEMORY_WT | EFI_MEMORY_WB;
 495                        mem_flags &= md.attribute;
 496                }
 497        }
 498        if (mem_flags & EFI_MEMORY_WC)
 499                info->screen_base = ioremap_wc(efifb_fix.smem_start,
 500                                               efifb_fix.smem_len);
 501        else if (mem_flags & EFI_MEMORY_UC)
 502                info->screen_base = ioremap(efifb_fix.smem_start,
 503                                            efifb_fix.smem_len);
 504        else if (mem_flags & EFI_MEMORY_WT)
 505                info->screen_base = memremap(efifb_fix.smem_start,
 506                                             efifb_fix.smem_len, MEMREMAP_WT);
 507        else if (mem_flags & EFI_MEMORY_WB)
 508                info->screen_base = memremap(efifb_fix.smem_start,
 509                                             efifb_fix.smem_len, MEMREMAP_WB);
 510        if (!info->screen_base) {
 511                pr_err("efifb: abort, cannot remap video memory 0x%x @ 0x%lx\n",
 512                        efifb_fix.smem_len, efifb_fix.smem_start);
 513                err = -EIO;
 514                goto err_release_fb;
 515        }
 516
 517        efifb_show_boot_graphics(info);
 518
 519        pr_info("efifb: framebuffer at 0x%lx, using %dk, total %dk\n",
 520               efifb_fix.smem_start, size_remap/1024, size_total/1024);
 521        pr_info("efifb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
 522               efifb_defined.xres, efifb_defined.yres,
 523               efifb_defined.bits_per_pixel, efifb_fix.line_length,
 524               screen_info.pages);
 525
 526        efifb_defined.xres_virtual = efifb_defined.xres;
 527        efifb_defined.yres_virtual = efifb_fix.smem_len /
 528                                        efifb_fix.line_length;
 529        pr_info("efifb: scrolling: redraw\n");
 530        efifb_defined.yres_virtual = efifb_defined.yres;
 531
 532        /* some dummy values for timing to make fbset happy */
 533        efifb_defined.pixclock     = 10000000 / efifb_defined.xres *
 534                                        1000 / efifb_defined.yres;
 535        efifb_defined.left_margin  = (efifb_defined.xres / 8) & 0xf8;
 536        efifb_defined.hsync_len    = (efifb_defined.xres / 8) & 0xf8;
 537
 538        efifb_defined.red.offset    = screen_info.red_pos;
 539        efifb_defined.red.length    = screen_info.red_size;
 540        efifb_defined.green.offset  = screen_info.green_pos;
 541        efifb_defined.green.length  = screen_info.green_size;
 542        efifb_defined.blue.offset   = screen_info.blue_pos;
 543        efifb_defined.blue.length   = screen_info.blue_size;
 544        efifb_defined.transp.offset = screen_info.rsvd_pos;
 545        efifb_defined.transp.length = screen_info.rsvd_size;
 546
 547        pr_info("efifb: %s: "
 548               "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
 549               "Truecolor",
 550               screen_info.rsvd_size,
 551               screen_info.red_size,
 552               screen_info.green_size,
 553               screen_info.blue_size,
 554               screen_info.rsvd_pos,
 555               screen_info.red_pos,
 556               screen_info.green_pos,
 557               screen_info.blue_pos);
 558
 559        efifb_fix.ypanstep  = 0;
 560        efifb_fix.ywrapstep = 0;
 561
 562        info->fbops = &efifb_ops;
 563        info->var = efifb_defined;
 564        info->fix = efifb_fix;
 565        info->flags = FBINFO_FLAG_DEFAULT | FBINFO_MISC_FIRMWARE;
 566
 567        orientation = drm_get_panel_orientation_quirk(efifb_defined.xres,
 568                                                      efifb_defined.yres);
 569        switch (orientation) {
 570        default:
 571                info->fbcon_rotate_hint = FB_ROTATE_UR;
 572                break;
 573        case DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP:
 574                info->fbcon_rotate_hint = FB_ROTATE_UD;
 575                break;
 576        case DRM_MODE_PANEL_ORIENTATION_LEFT_UP:
 577                info->fbcon_rotate_hint = FB_ROTATE_CCW;
 578                break;
 579        case DRM_MODE_PANEL_ORIENTATION_RIGHT_UP:
 580                info->fbcon_rotate_hint = FB_ROTATE_CW;
 581                break;
 582        }
 583
 584        err = sysfs_create_groups(&dev->dev.kobj, efifb_groups);
 585        if (err) {
 586                pr_err("efifb: cannot add sysfs attrs\n");
 587                goto err_unmap;
 588        }
 589        err = fb_alloc_cmap(&info->cmap, 256, 0);
 590        if (err < 0) {
 591                pr_err("efifb: cannot allocate colormap\n");
 592                goto err_groups;
 593        }
 594
 595        if (efifb_pci_dev)
 596                WARN_ON(pm_runtime_get_sync(&efifb_pci_dev->dev) < 0);
 597
 598        err = register_framebuffer(info);
 599        if (err < 0) {
 600                pr_err("efifb: cannot register framebuffer\n");
 601                goto err_put_rpm_ref;
 602        }
 603        fb_info(info, "%s frame buffer device\n", info->fix.id);
 604        return 0;
 605
 606err_put_rpm_ref:
 607        if (efifb_pci_dev)
 608                pm_runtime_put(&efifb_pci_dev->dev);
 609
 610        fb_dealloc_cmap(&info->cmap);
 611err_groups:
 612        sysfs_remove_groups(&dev->dev.kobj, efifb_groups);
 613err_unmap:
 614        if (mem_flags & (EFI_MEMORY_UC | EFI_MEMORY_WC))
 615                iounmap(info->screen_base);
 616        else
 617                memunmap(info->screen_base);
 618err_release_fb:
 619        framebuffer_release(info);
 620err_release_mem:
 621        if (request_mem_succeeded)
 622                release_mem_region(efifb_fix.smem_start, size_total);
 623        return err;
 624}
 625
 626static int efifb_remove(struct platform_device *pdev)
 627{
 628        struct fb_info *info = platform_get_drvdata(pdev);
 629
 630        /* efifb_destroy takes care of info cleanup */
 631        unregister_framebuffer(info);
 632        sysfs_remove_groups(&pdev->dev.kobj, efifb_groups);
 633
 634        return 0;
 635}
 636
 637static struct platform_driver efifb_driver = {
 638        .driver = {
 639                .name = "efi-framebuffer",
 640        },
 641        .probe = efifb_probe,
 642        .remove = efifb_remove,
 643};
 644
 645builtin_platform_driver(efifb_driver);
 646
 647#if defined(CONFIG_PCI)
 648
 649static void record_efifb_bar_resource(struct pci_dev *dev, int idx, u64 offset)
 650{
 651        u16 word;
 652
 653        efifb_pci_dev = dev;
 654
 655        pci_read_config_word(dev, PCI_COMMAND, &word);
 656        if (!(word & PCI_COMMAND_MEMORY)) {
 657                pci_dev_disabled = true;
 658                dev_err(&dev->dev,
 659                        "BAR %d: assigned to efifb but device is disabled!\n",
 660                        idx);
 661                return;
 662        }
 663
 664        bar_resource = &dev->resource[idx];
 665        bar_offset = offset;
 666
 667        dev_info(&dev->dev, "BAR %d: assigned to efifb\n", idx);
 668}
 669
 670static void efifb_fixup_resources(struct pci_dev *dev)
 671{
 672        u64 base = screen_info.lfb_base;
 673        u64 size = screen_info.lfb_size;
 674        int i;
 675
 676        if (efifb_pci_dev || screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
 677                return;
 678
 679        if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)
 680                base |= (u64)screen_info.ext_lfb_base << 32;
 681
 682        if (!base)
 683                return;
 684
 685        for (i = 0; i < PCI_STD_NUM_BARS; i++) {
 686                struct resource *res = &dev->resource[i];
 687
 688                if (!(res->flags & IORESOURCE_MEM))
 689                        continue;
 690
 691                if (res->start <= base && res->end >= base + size - 1) {
 692                        record_efifb_bar_resource(dev, i, base - res->start);
 693                        break;
 694                }
 695        }
 696}
 697DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY,
 698                               16, efifb_fixup_resources);
 699
 700#endif
 701