]>
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 */
33 static 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
)
37 struct efi_gop_obj
*gopobj
;
39 EFI_ENTRY("%p, %x, %p, %p", this, mode_number
, size_of_info
, info
);
41 gopobj
= container_of(this, struct efi_gop_obj
, ops
);
42 *size_of_info
= sizeof(gopobj
->info
);
43 *info
= &gopobj
->info
;
45 return EFI_EXIT(EFI_SUCCESS
);
48 static efi_status_t EFIAPI
gop_set_mode(struct efi_gop
*this, u32 mode_number
)
50 EFI_ENTRY("%p, %x", this, mode_number
);
53 return EFI_EXIT(EFI_INVALID_PARAMETER
);
55 return EFI_EXIT(EFI_SUCCESS
);
58 static 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
)
64 struct efi_gop_obj
*gopobj
= container_of(this, struct efi_gop_obj
, ops
);
65 int i
, j
, line_len16
, line_len32
;
68 EFI_ENTRY("%p, %p, %lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx", this,
69 buffer
, operation
, sx
, sy
, dx
, dy
, width
, height
, delta
);
71 if (operation
!= EFI_BLT_BUFFER_TO_VIDEO
)
72 return EFI_EXIT(EFI_INVALID_PARAMETER
);
74 fb
= (void*)gd
->fb_base
;
75 line_len16
= gopobj
->info
.width
* sizeof(u16
);
76 line_len32
= gopobj
->info
.width
* sizeof(u32
);
78 /* Copy the contents line by line */
80 switch (gopobj
->bpix
) {
81 #ifdef CONFIG_DM_VIDEO
86 for (i
= 0; i
< height
; i
++) {
87 u32
*dest
= fb
+ ((i
+ dy
) * line_len32
) +
89 u32
*src
= buffer
+ ((i
+ sy
) * line_len32
) +
92 /* Same color format, just memcpy */
93 memcpy(dest
, src
, width
* sizeof(u32
));
96 #ifdef CONFIG_DM_VIDEO
101 for (i
= 0; i
< height
; i
++) {
102 u16
*dest
= fb
+ ((i
+ dy
) * line_len16
) +
104 u32
*src
= buffer
+ ((i
+ sy
) * line_len32
) +
107 /* Convert from rgb888 to rgb565 */
108 for (j
= 0; j
< width
; j
++) {
110 dest
[j
] = ((((rgb888
>> (16 + 3)) & 0x1f) << 11) |
111 (((rgb888
>> (8 + 2)) & 0x3f) << 5) |
112 (((rgb888
>> (0 + 3)) & 0x1f) << 0));
118 #ifdef CONFIG_DM_VIDEO
124 return EFI_EXIT(EFI_SUCCESS
);
127 /* This gets called from do_bootefi_exec(). */
128 int efi_gop_register(void)
130 struct efi_gop_obj
*gopobj
;
132 u64 fb_base
, fb_size
;
134 #ifdef CONFIG_DM_VIDEO
135 struct udevice
*vdev
;
137 /* We only support a single video output device for now */
138 if (uclass_first_device(UCLASS_VIDEO
, &vdev
))
141 struct video_priv
*priv
= dev_get_uclass_priv(vdev
);
143 col
= video_get_xsize(vdev
);
144 row
= video_get_ysize(vdev
);
145 fb_base
= (uintptr_t)priv
->fb
;
146 fb_size
= priv
->fb_size
;
150 bpix
= panel_info
.vl_bpix
;
151 col
= panel_info
.vl_col
;
152 row
= panel_info
.vl_row
;
153 fb_base
= gd
->fb_base
;
154 fb_size
= lcd_get_size(&line_len
);
158 #ifdef CONFIG_DM_VIDEO
167 /* So far, we only work in 16 or 32 bit mode */
171 gopobj
= calloc(1, sizeof(*gopobj
));
173 /* Fill in object data */
174 gopobj
->parent
.protocols
[0].guid
= &efi_gop_guid
;
175 gopobj
->parent
.protocols
[0].open
= efi_return_handle
;
176 gopobj
->parent
.handle
= &gopobj
->ops
;
177 gopobj
->ops
.query_mode
= gop_query_mode
;
178 gopobj
->ops
.set_mode
= gop_set_mode
;
179 gopobj
->ops
.blt
= gop_blt
;
180 gopobj
->ops
.mode
= &gopobj
->mode
;
182 gopobj
->mode
.max_mode
= 1;
183 gopobj
->mode
.info
= &gopobj
->info
;
184 gopobj
->mode
.info_size
= sizeof(gopobj
->info
);
186 #ifdef CONFIG_DM_VIDEO
187 if (bpix
== VIDEO_BPP32
) {
189 if (bpix
== LCD_COLOR32
) {
191 /* With 32bit color space we can directly expose the fb */
192 gopobj
->mode
.fb_base
= fb_base
;
193 gopobj
->mode
.fb_size
= fb_size
;
196 gopobj
->info
.version
= 0;
197 gopobj
->info
.width
= col
;
198 gopobj
->info
.height
= row
;
199 gopobj
->info
.pixel_format
= EFI_GOT_RGBA8
;
200 gopobj
->info
.pixels_per_scanline
= col
;
204 /* Hook up to the device list */
205 list_add_tail(&gopobj
->parent
.link
, &efi_obj_list
);