efi: stub: Pass EFI GOP information to U-Boot payload
authorBin Meng <bmeng.cn@gmail.com>
Tue, 12 Jun 2018 15:36:21 +0000 (08:36 -0700)
committerBin Meng <bmeng.cn@gmail.com>
Sun, 17 Jun 2018 13:16:04 +0000 (21:16 +0800)
If UEFI BIOS has the graphics output protocol (GOP), let's pass its
information to U-Boot payload so that U-Boot can utilize it (eg:
an EFI framebuffer driver).

Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
include/efi.h
lib/efi/efi_stub.c

index e30a3c51c676f3777eb399de981cafd2ee6ffe80..2448dde3fe7643fe22d0c7c4c0ca1ca62ce56ef3 100644 (file)
@@ -241,6 +241,7 @@ struct efi_open_protocol_info_entry {
 enum efi_entry_t {
        EFIET_END,      /* Signals this is the last (empty) entry */
        EFIET_MEMORY_MAP,
+       EFIET_GOP_MODE,
 
        /* Number of entries */
        EFIET_MEMORY_COUNT,
@@ -297,6 +298,40 @@ struct efi_entry_memmap {
        struct efi_mem_desc desc[];
 };
 
+/**
+ * struct efi_entry_gopmode - a GOP mode table passed to U-Boot
+ *
+ * @fb_base:   EFI's framebuffer base address
+ * @fb_size:   EFI's framebuffer size
+ * @info_size: GOP mode info structure size
+ * @info:      Start address of the GOP mode info structure
+ */
+struct efi_entry_gopmode {
+       efi_physical_addr_t fb_base;
+       /*
+        * Not like the ones in 'struct efi_gop_mode' which are 'unsigned
+        * long', @fb_size and @info_size have to be 'u64' here. As the EFI
+        * stub codes may have different bit size from the U-Boot payload,
+        * using 'long' will cause mismatch between the producer (stub) and
+        * the consumer (payload).
+        */
+       u64 fb_size;
+       u64 info_size;
+       /*
+        * We cannot directly use 'struct efi_gop_mode_info info[]' here as
+        * it causes compiler to complain: array type has incomplete element
+        * type 'struct efi_gop_mode_info'.
+        */
+       struct /* efi_gop_mode_info */ {
+               u32 version;
+               u32 width;
+               u32 height;
+               u32 pixel_format;
+               u32 pixel_bitmask[4];
+               u32 pixels_per_scanline;
+       } info[];
+};
+
 static inline struct efi_mem_desc *efi_get_next_mem_desc(
                struct efi_entry_memmap *map, struct efi_mem_desc *desc)
 {
index 9deffe220febbc371641a9b13016be2c4c076803..262fc56562f331584c2f0c07a746817f9e13eac3 100644 (file)
@@ -275,6 +275,9 @@ efi_status_t EFIAPI efi_main(efi_handle_t image,
        struct efi_boot_services *boot = sys_table->boottime;
        struct efi_mem_desc *desc;
        struct efi_entry_memmap map;
+       struct efi_gop *gop;
+       struct efi_entry_gopmode mode;
+       efi_guid_t efi_gop_guid = EFI_GOP_GUID;
        efi_uintn_t key, desc_size, size;
        efi_status_t ret;
        u32 version;
@@ -313,6 +316,18 @@ efi_status_t EFIAPI efi_main(efi_handle_t image,
        if (ret)
                return ret;
 
+       ret = boot->locate_protocol(&efi_gop_guid, NULL, (void **)&gop);
+       if (ret) {
+               puts(" GOP unavailable\n");
+       } else {
+               mode.fb_base = gop->mode->fb_base;
+               mode.fb_size = gop->mode->fb_size;
+               mode.info_size = gop->mode->info_size;
+               add_entry_addr(priv, EFIET_GOP_MODE, &mode, sizeof(mode),
+                              gop->mode->info,
+                              sizeof(struct efi_gop_mode_info));
+       }
+
        ret = boot->get_memory_map(&size, desc, &key, &desc_size, &version);
        if (ret) {
                printhex2(ret);