uboot/lib/efi_loader/efi_gop.c
<<
>>
Prefs
   1/*
   2 *  EFI application disk support
   3 *
   4 *  Copyright (c) 2016 Alexander Graf
   5 *
   6 *  SPDX-License-Identifier:     GPL-2.0+
   7 */
   8
   9#include <common.h>
  10#include <dm.h>
  11#include <efi_loader.h>
  12#include <inttypes.h>
  13#include <lcd.h>
  14#include <malloc.h>
  15#include <video.h>
  16
  17DECLARE_GLOBAL_DATA_PTR;
  18
  19static const efi_guid_t efi_gop_guid = EFI_GOP_GUID;
  20
  21struct efi_gop_obj {
  22        /* Generic EFI object parent class data */
  23        struct efi_object parent;
  24        /* EFI Interface callback struct for gop */
  25        struct efi_gop ops;
  26        /* The only mode we support */
  27        struct efi_gop_mode_info info;
  28        struct efi_gop_mode mode;
  29        /* Fields we only have acces to during init */
  30        u32 bpix;
  31};
  32
  33static efi_status_t EFIAPI gop_query_mode(struct efi_gop *this, u32 mode_number,
  34                                          unsigned long *size_of_info,
  35                                          struct efi_gop_mode_info **info)
  36{
  37        struct efi_gop_obj *gopobj;
  38
  39        EFI_ENTRY("%p, %x, %p, %p", this, mode_number, size_of_info, info);
  40
  41        gopobj = container_of(this, struct efi_gop_obj, ops);
  42        *size_of_info = sizeof(gopobj->info);
  43        *info = &gopobj->info;
  44
  45        return EFI_EXIT(EFI_SUCCESS);
  46}
  47
  48static efi_status_t EFIAPI gop_set_mode(struct efi_gop *this, u32 mode_number)
  49{
  50        EFI_ENTRY("%p, %x", this, mode_number);
  51
  52        if (mode_number != 0)
  53                return EFI_EXIT(EFI_INVALID_PARAMETER);
  54
  55        return EFI_EXIT(EFI_SUCCESS);
  56}
  57
  58static efi_status_t EFIAPI gop_blt(struct efi_gop *this, void *buffer,
  59                                   unsigned long operation, unsigned long sx,
  60                                   unsigned long sy, unsigned long dx,
  61                                   unsigned long dy, unsigned long width,
  62                                   unsigned long height, unsigned long delta)
  63{
  64        struct efi_gop_obj *gopobj = container_of(this, struct efi_gop_obj, ops);
  65        int i, j, line_len16, line_len32;
  66        void *fb;
  67
  68        EFI_ENTRY("%p, %p, %lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx", this,
  69                  buffer, operation, sx, sy, dx, dy, width, height, delta);
  70
  71        if (operation != EFI_BLT_BUFFER_TO_VIDEO)
  72                return EFI_EXIT(EFI_INVALID_PARAMETER);
  73
  74        fb = (void*)gd->fb_base;
  75        line_len16 = gopobj->info.width * sizeof(u16);
  76        line_len32 = gopobj->info.width * sizeof(u32);
  77
  78        /* Copy the contents line by line */
  79
  80        switch (gopobj->bpix) {
  81#ifdef CONFIG_DM_VIDEO
  82        case VIDEO_BPP32:
  83#else
  84        case LCD_COLOR32:
  85#endif
  86                for (i = 0; i < height; i++) {
  87                        u32 *dest = fb + ((i + dy)  * line_len32) +
  88                                         (dx * sizeof(u32));
  89                        u32 *src = buffer + ((i + sy)  * line_len32) +
  90                                         (sx * sizeof(u32));
  91
  92                        /* Same color format, just memcpy */
  93                        memcpy(dest, src, width * sizeof(u32));
  94                }
  95                break;
  96#ifdef CONFIG_DM_VIDEO
  97        case VIDEO_BPP16:
  98#else
  99        case LCD_COLOR16:
 100#endif
 101                for (i = 0; i < height; i++) {
 102                        u16 *dest = fb + ((i + dy)  * line_len16) +
 103                                         (dx * sizeof(u16));
 104                        u32 *src = buffer + ((i + sy)  * line_len32) +
 105                                         (sx * sizeof(u32));
 106
 107                        /* Convert from rgb888 to rgb565 */
 108                        for (j = 0; j < width; j++) {
 109                                u32 rgb888 = src[j];
 110                                dest[j] = ((((rgb888 >> (16 + 3)) & 0x1f) << 11) |
 111                                           (((rgb888 >> (8 + 2)) & 0x3f) << 5) |
 112                                           (((rgb888 >> (0 + 3)) & 0x1f) << 0));
 113                        }
 114                }
 115                break;
 116        }
 117
 118#ifdef CONFIG_DM_VIDEO
 119        video_sync_all();
 120#else
 121        lcd_sync();
 122#endif
 123
 124        return EFI_EXIT(EFI_SUCCESS);
 125}
 126
 127/* This gets called from do_bootefi_exec(). */
 128int efi_gop_register(void)
 129{
 130        struct efi_gop_obj *gopobj;
 131        u32 bpix, col, row;
 132
 133#ifdef CONFIG_DM_VIDEO
 134        struct udevice *vdev;
 135
 136        /* We only support a single video output device for now */
 137        if (uclass_first_device(UCLASS_VIDEO, &vdev))
 138                return -1;
 139
 140        struct video_priv *priv = dev_get_uclass_priv(vdev);
 141        bpix = priv->bpix;
 142        col = video_get_xsize(vdev);
 143        row = video_get_ysize(vdev);
 144#else
 145
 146        bpix = panel_info.vl_bpix;
 147        col = panel_info.vl_col;
 148        row = panel_info.vl_row;
 149#endif
 150
 151        switch (bpix) {
 152#ifdef CONFIG_DM_VIDEO
 153        case VIDEO_BPP16:
 154        case VIDEO_BPP32:
 155#else
 156        case LCD_COLOR32:
 157        case LCD_COLOR16:
 158#endif
 159                break;
 160        default:
 161                /* So far, we only work in 16 or 32 bit mode */
 162                return -1;
 163        }
 164
 165        gopobj = calloc(1, sizeof(*gopobj));
 166
 167        /* Fill in object data */
 168        gopobj->parent.protocols[0].guid = &efi_gop_guid;
 169        gopobj->parent.protocols[0].open = efi_return_handle;
 170        gopobj->parent.handle = &gopobj->ops;
 171        gopobj->ops.query_mode = gop_query_mode;
 172        gopobj->ops.set_mode = gop_set_mode;
 173        gopobj->ops.blt = gop_blt;
 174        gopobj->ops.mode = &gopobj->mode;
 175
 176        gopobj->mode.max_mode = 1;
 177        gopobj->mode.info = &gopobj->info;
 178        gopobj->mode.info_size = sizeof(gopobj->info);
 179
 180        gopobj->info.version = 0;
 181        gopobj->info.width = col;
 182        gopobj->info.height = row;
 183        gopobj->info.pixel_format = EFI_GOT_RGBA8;
 184        gopobj->info.pixels_per_scanline = col;
 185
 186        gopobj->bpix = bpix;
 187
 188        /* Hook up to the device list */
 189        list_add_tail(&gopobj->parent.link, &efi_obj_list);
 190
 191        return 0;
 192}
 193