]>
git.ipfire.org Git - people/ms/u-boot.git/blob - lib/efi_loader/efi_gop.c
2 * EFI application disk support
4 * Copyright (c) 2016 Alexander Graf
6 * SPDX-License-Identifier: GPL-2.0+
11 #include <efi_loader.h>
17 DECLARE_GLOBAL_DATA_PTR
;
19 static const efi_guid_t efi_gop_guid
= EFI_GOP_GUID
;
22 /* Generic EFI object parent class data */
23 struct efi_object parent
;
24 /* EFI Interface callback struct for gop */
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 */
34 static efi_status_t EFIAPI
gop_query_mode(struct efi_gop
*this, u32 mode_number
,
35 efi_uintn_t
*size_of_info
,
36 struct efi_gop_mode_info
**info
)
38 struct efi_gop_obj
*gopobj
;
40 EFI_ENTRY("%p, %x, %p, %p", this, mode_number
, size_of_info
, info
);
42 gopobj
= container_of(this, struct efi_gop_obj
, ops
);
43 *size_of_info
= sizeof(gopobj
->info
);
44 *info
= &gopobj
->info
;
46 return EFI_EXIT(EFI_SUCCESS
);
49 static efi_status_t EFIAPI
gop_set_mode(struct efi_gop
*this, u32 mode_number
)
51 EFI_ENTRY("%p, %x", this, mode_number
);
54 return EFI_EXIT(EFI_INVALID_PARAMETER
);
56 return EFI_EXIT(EFI_SUCCESS
);
59 efi_status_t EFIAPI
gop_blt(struct efi_gop
*this, void *buffer
,
60 u32 operation
, efi_uintn_t sx
,
61 efi_uintn_t sy
, efi_uintn_t dx
,
62 efi_uintn_t dy
, efi_uintn_t width
,
63 efi_uintn_t height
, efi_uintn_t delta
)
65 struct efi_gop_obj
*gopobj
= container_of(this, struct efi_gop_obj
, ops
);
66 int i
, j
, line_len16
, line_len32
;
69 EFI_ENTRY("%p, %p, %u, %zu, %zu, %zu, %zu, %zu, %zu, %zu", this,
70 buffer
, operation
, sx
, sy
, dx
, dy
, width
, height
, delta
);
72 if (operation
!= EFI_BLT_BUFFER_TO_VIDEO
)
73 return EFI_EXIT(EFI_INVALID_PARAMETER
);
76 line_len16
= gopobj
->info
.width
* sizeof(u16
);
77 line_len32
= gopobj
->info
.width
* sizeof(u32
);
79 /* Copy the contents line by line */
81 switch (gopobj
->bpix
) {
82 #ifdef CONFIG_DM_VIDEO
87 for (i
= 0; i
< height
; i
++) {
88 u32
*dest
= fb
+ ((i
+ dy
) * line_len32
) +
90 u32
*src
= buffer
+ ((i
+ sy
) * line_len32
) +
93 /* Same color format, just memcpy */
94 memcpy(dest
, src
, width
* sizeof(u32
));
97 #ifdef CONFIG_DM_VIDEO
102 for (i
= 0; i
< height
; i
++) {
103 u16
*dest
= fb
+ ((i
+ dy
) * line_len16
) +
105 u32
*src
= buffer
+ ((i
+ sy
) * line_len32
) +
108 /* Convert from rgb888 to rgb565 */
109 for (j
= 0; j
< width
; j
++) {
111 dest
[j
] = ((((rgb888
>> (16 + 3)) & 0x1f) << 11) |
112 (((rgb888
>> (8 + 2)) & 0x3f) << 5) |
113 (((rgb888
>> (0 + 3)) & 0x1f) << 0));
119 #ifdef CONFIG_DM_VIDEO
125 return EFI_EXIT(EFI_SUCCESS
);
128 /* This gets called from do_bootefi_exec(). */
129 int efi_gop_register(void)
131 struct efi_gop_obj
*gopobj
;
133 u64 fb_base
, fb_size
;
137 #ifdef CONFIG_DM_VIDEO
138 struct udevice
*vdev
;
140 /* We only support a single video output device for now */
141 if (uclass_first_device(UCLASS_VIDEO
, &vdev
) || !vdev
)
144 struct video_priv
*priv
= dev_get_uclass_priv(vdev
);
146 col
= video_get_xsize(vdev
);
147 row
= video_get_ysize(vdev
);
148 fb_base
= (uintptr_t)priv
->fb
;
149 fb_size
= priv
->fb_size
;
154 bpix
= panel_info
.vl_bpix
;
155 col
= panel_info
.vl_col
;
156 row
= panel_info
.vl_row
;
157 fb_base
= gd
->fb_base
;
158 fb_size
= lcd_get_size(&line_len
);
159 fb
= (void*)gd
->fb_base
;
163 #ifdef CONFIG_DM_VIDEO
172 /* So far, we only work in 16 or 32 bit mode */
176 gopobj
= calloc(1, sizeof(*gopobj
));
178 printf("ERROR: Out of memory\n");
182 /* Hook up to the device list */
183 efi_add_handle(&gopobj
->parent
);
185 /* Fill in object data */
186 ret
= efi_add_protocol(gopobj
->parent
.handle
, &efi_gop_guid
,
188 if (ret
!= EFI_SUCCESS
) {
189 printf("ERROR: Out of memory\n");
192 gopobj
->ops
.query_mode
= gop_query_mode
;
193 gopobj
->ops
.set_mode
= gop_set_mode
;
194 gopobj
->ops
.blt
= gop_blt
;
195 gopobj
->ops
.mode
= &gopobj
->mode
;
197 gopobj
->mode
.max_mode
= 1;
198 gopobj
->mode
.info
= &gopobj
->info
;
199 gopobj
->mode
.info_size
= sizeof(gopobj
->info
);
201 #ifdef CONFIG_DM_VIDEO
202 if (bpix
== VIDEO_BPP32
) {
204 if (bpix
== LCD_COLOR32
) {
206 /* With 32bit color space we can directly expose the fb */
207 gopobj
->mode
.fb_base
= fb_base
;
208 gopobj
->mode
.fb_size
= fb_size
;
211 gopobj
->info
.version
= 0;
212 gopobj
->info
.width
= col
;
213 gopobj
->info
.height
= row
;
214 gopobj
->info
.pixel_format
= EFI_GOT_RGBA8
;
215 gopobj
->info
.pixels_per_scanline
= col
;