1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
5 * EFI framebuffer driver based on GOP
8 #define LOG_CATEGORY LOGC_EFI
21 static const struct efi_framebuffer
{
26 } efi_framebuffer_format_map
[] = {
27 [EFI_GOT_RGBA8
] = { {0, 8}, {8, 8}, {16, 8}, {24, 8} },
28 [EFI_GOT_BGRA8
] = { {16, 8}, {8, 8}, {0, 8}, {24, 8} },
31 static void efi_find_pixel_bits(u32 mask
, u8
*pos
, u8
*size
)
39 while (!(mask
& 0x1)) {
55 * get_mode_info() - Ask EFI for the mode information
57 * Gets info from the graphics-output protocol
59 * @vesa: Place to put the mode information
60 * @fbp: Returns the address of the frame buffer
61 * @infop: Returns a pointer to the mode info
62 * Returns: 0 if OK, -ENOSYS if boot services are not available, -ENOTSUPP if
63 * the protocol is not supported by EFI
65 static int get_mode_info(struct vesa_mode_info
*vesa
, u64
*fbp
,
66 struct efi_gop_mode_info
**infop
)
68 efi_guid_t efi_gop_guid
= EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID
;
69 struct efi_boot_services
*boot
= efi_get_boot();
70 struct efi_gop_mode
*mode
;
75 return log_msg_ret("sys", -ENOSYS
);
76 ret
= boot
->locate_protocol(&efi_gop_guid
, NULL
, (void **)&gop
);
78 return log_msg_ret("prot", -ENOTSUPP
);
80 log_debug("maxmode %u, mode %u, info %p, size %lx, fb %lx, fb_size %lx\n",
81 mode
->max_mode
, mode
->mode
, mode
->info
, mode
->info_size
,
82 (ulong
)mode
->fb_base
, (ulong
)mode
->fb_size
);
84 vesa
->phys_base_ptr
= mode
->fb_base
;
86 vesa
->x_resolution
= mode
->info
->width
;
87 vesa
->y_resolution
= mode
->info
->height
;
94 * get_mode_from_entry() - Obtain fb info from the EFIET_GOP_MODE payload entry
96 * This gets the mode information provided by the stub to the payload and puts
97 * it into a vesa structure. It also returns the mode information.
99 * @vesa: Place to put the mode information
100 * @fbp: Returns the address of the frame buffer
101 * @infop: Returns a pointer to the mode info
102 * Returns: 0 if OK, -ve on error
104 static int get_mode_from_entry(struct vesa_mode_info
*vesa
, u64
*fbp
,
105 struct efi_gop_mode_info
**infop
)
107 struct efi_gop_mode
*mode
;
111 ret
= efi_info_get(EFIET_GOP_MODE
, (void **)&mode
, &size
);
113 printf("EFI graphics output entry not found\n");
116 vesa
->phys_base_ptr
= mode
->fb_base
;
117 *fbp
= mode
->fb_base
;
118 vesa
->x_resolution
= mode
->info
->width
;
119 vesa
->y_resolution
= mode
->info
->height
;
125 static int save_vesa_mode(struct vesa_mode_info
*vesa
, u64
*fbp
)
127 const struct efi_framebuffer
*fbinfo
;
128 struct efi_gop_mode_info
*info
;
131 if (IS_ENABLED(CONFIG_EFI_APP
))
132 ret
= get_mode_info(vesa
, fbp
, &info
);
134 ret
= get_mode_from_entry(vesa
, fbp
, &info
);
136 printf("EFI graphics output protocol not found (err=%dE)\n",
141 if (info
->pixel_format
< EFI_GOT_BITMASK
) {
142 fbinfo
= &efi_framebuffer_format_map
[info
->pixel_format
];
143 vesa
->red_mask_size
= fbinfo
->red
.size
;
144 vesa
->red_mask_pos
= fbinfo
->red
.pos
;
145 vesa
->green_mask_size
= fbinfo
->green
.size
;
146 vesa
->green_mask_pos
= fbinfo
->green
.pos
;
147 vesa
->blue_mask_size
= fbinfo
->blue
.size
;
148 vesa
->blue_mask_pos
= fbinfo
->blue
.pos
;
149 vesa
->reserved_mask_size
= fbinfo
->rsvd
.size
;
150 vesa
->reserved_mask_pos
= fbinfo
->rsvd
.pos
;
152 vesa
->bits_per_pixel
= 32;
153 vesa
->bytes_per_scanline
= info
->pixels_per_scanline
* 4;
154 } else if (info
->pixel_format
== EFI_GOT_BITMASK
) {
155 efi_find_pixel_bits(info
->pixel_bitmask
[0],
157 &vesa
->red_mask_size
);
158 efi_find_pixel_bits(info
->pixel_bitmask
[1],
159 &vesa
->green_mask_pos
,
160 &vesa
->green_mask_size
);
161 efi_find_pixel_bits(info
->pixel_bitmask
[2],
162 &vesa
->blue_mask_pos
,
163 &vesa
->blue_mask_size
);
164 efi_find_pixel_bits(info
->pixel_bitmask
[3],
165 &vesa
->reserved_mask_pos
,
166 &vesa
->reserved_mask_size
);
167 vesa
->bits_per_pixel
= vesa
->red_mask_size
+
168 vesa
->green_mask_size
+
169 vesa
->blue_mask_size
+
170 vesa
->reserved_mask_size
;
171 vesa
->bytes_per_scanline
= (info
->pixels_per_scanline
*
172 vesa
->bits_per_pixel
) / 8;
174 log_err("Unknown framebuffer format: %d\n", info
->pixel_format
);
181 static int efi_video_probe(struct udevice
*dev
)
183 struct video_uc_plat
*plat
= dev_get_uclass_plat(dev
);
184 struct video_priv
*uc_priv
= dev_get_uclass_priv(dev
);
185 struct vesa_mode_info
*vesa
= &mode_info
.vesa
;
189 /* Initialize vesa_mode_info structure */
190 ret
= save_vesa_mode(vesa
, &fb
);
194 ret
= vesa_setup_video_priv(vesa
, fb
, uc_priv
, plat
);
198 printf("Video: %dx%dx%d @ %lx\n", uc_priv
->xsize
, uc_priv
->ysize
,
199 vesa
->bits_per_pixel
, (ulong
)fb
);
204 printf("No video mode configured in EFI!\n");
208 static int efi_video_bind(struct udevice
*dev
)
210 if (IS_ENABLED(CONFIG_VIDEO_COPY
)) {
211 struct video_uc_plat
*plat
= dev_get_uclass_plat(dev
);
212 struct vesa_mode_info vesa
;
217 * Initialise vesa_mode_info structure so we can figure out the
218 * required framebuffer size. If something goes wrong, just do
219 * without a copy framebuffer
221 ret
= save_vesa_mode(&vesa
, &fb
);
223 /* this is not reached if the EFI call failed */
224 plat
->copy_size
= vesa
.bytes_per_scanline
*
232 static const struct udevice_id efi_video_ids
[] = {
233 { .compatible
= "efi-fb" },
237 U_BOOT_DRIVER(efi_video
) = {
240 .of_match
= efi_video_ids
,
241 .bind
= efi_video_bind
,
242 .probe
= efi_video_probe
,