[PATCH v3 00/13] video: efi: Improve the EFI-app video console

This does not work on some 64-bit machines since only a 32-bit address for the framebuffer is supported in the VESA structure.
This series corrects this and makes a few other minor, video-related improvements.
Changes in v3: - Use Returns instead of @return - Show the CPU vendor name also - Add a comment about the value - Add a comment about the fallback
Changes in v2: - Obtain copy framebuffer size from EFI instead of using a fixed value - Dropping debugging printf() - Use new bootph-xxx tag - Add new patch to show the size of the copy framebuffer with bdinfo
Simon Glass (13): efi: video: Move payload code into a function efi: video: Return mode info for app also efi: Support a 64-bit frame buffer address x86: Add a few more items to bdinfo efi: Use a fixed value for the timer clock efi: Support copy framebuffer video: Allow a copy framebuffer with pre-allocated fb bbinfo: Show the size of the copy framebuffer efi: Adjust script to show pre-relocation output on terminal video: Remove duplicate cursor-positioning function video: Clear the vidconsole rather than the video efi: Add dhrystone, dcache and scroll lines to app video: Add a note about the broken implementation
arch/x86/dts/efi-x86_app.dts | 1 + arch/x86/lib/bdinfo.c | 6 ++ arch/x86/lib/fsp/fsp_graphics.c | 2 +- cmd/bdinfo.c | 11 ++- cmd/cls.c | 20 +++-- configs/efi-x86_app64_defconfig | 3 + drivers/pci/pci_rom.c | 10 ++- drivers/timer/tsc_timer.c | 9 ++ drivers/video/coreboot.c | 2 +- drivers/video/efi.c | 138 ++++++++++++++++++++++-------- drivers/video/vidconsole-uclass.c | 48 ++++------- drivers/video/video-uclass.c | 32 +++++-- include/init.h | 3 + include/vesa.h | 16 +++- include/video.h | 2 + include/video_console.h | 9 ++ scripts/build-efi.sh | 2 + 17 files changed, 228 insertions(+), 86 deletions(-)

Put this into a function, as we have done for the app implementation. Comment both functions. FOr now the app still does not access it correctly.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
drivers/video/efi.c | 83 +++++++++++++++++++++++++++++++-------------- 1 file changed, 57 insertions(+), 26 deletions(-)
diff --git a/drivers/video/efi.c b/drivers/video/efi.c index b11e42c0ebf..fc37a68b376 100644 --- a/drivers/video/efi.c +++ b/drivers/video/efi.c @@ -50,6 +50,15 @@ static void efi_find_pixel_bits(u32 mask, u8 *pos, u8 *size) *size = len; }
+/** + * get_mode_info() - Ask EFI for the mode information + * + * Gets info from the graphics-output protocol + * + * @vesa: Place to put the mode information + * Returns: 0 if OK, -ENOSYS if boot services are not available, -ENOTSUPP if + * the protocol is not supported by EFI + */ static int get_mode_info(struct vesa_mode_info *vesa) { efi_guid_t efi_gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; @@ -72,32 +81,54 @@ static int get_mode_info(struct vesa_mode_info *vesa) return 0; }
+/** + * get_mode_from_entry() - Obtain fb info from the EFIET_GOP_MODE payload entry + * + * This gets the mode information provided by the stub to the payload and puts + * it into a vesa structure. It also returns the mode information. + * + * @vesa: Place to put the mode information + * @infop: Returns a pointer to the mode info + * Returns: 0 if OK, -ve on error + */ +static int get_mode_from_entry(struct vesa_mode_info *vesa, + struct efi_gop_mode_info **infop) +{ + struct efi_gop_mode *mode; + int size; + int ret; + + ret = efi_info_get(EFIET_GOP_MODE, (void **)&mode, &size); + if (ret) { + printf("EFI graphics output entry not found\n"); + return ret; + } + vesa->phys_base_ptr = mode->fb_base; + vesa->x_resolution = mode->info->width; + vesa->y_resolution = mode->info->height; + *infop = mode->info; + + return 0; +} + static int save_vesa_mode(struct vesa_mode_info *vesa) { - struct efi_entry_gopmode *mode; const struct efi_framebuffer *fbinfo; - int size; + struct efi_gop_mode_info *info; int ret;
- if (IS_ENABLED(CONFIG_EFI_APP)) { + if (IS_ENABLED(CONFIG_EFI_APP)) ret = get_mode_info(vesa); - if (ret) { - printf("EFI graphics output protocol not found\n"); - return -ENXIO; - } - } else { - ret = efi_info_get(EFIET_GOP_MODE, (void **)&mode, &size); - if (ret == -ENOENT) { - printf("EFI graphics output protocol mode not found\n"); - return -ENXIO; - } - vesa->phys_base_ptr = mode->fb_base; - vesa->x_resolution = mode->info->width; - vesa->y_resolution = mode->info->height; + else + ret = get_mode_from_entry(vesa, &info); + if (ret) { + printf("EFI graphics output protocol not found (err=%dE)\n", + ret); + return ret; }
- if (mode->info->pixel_format < EFI_GOT_BITMASK) { - fbinfo = &efi_framebuffer_format_map[mode->info->pixel_format]; + if (info->pixel_format < EFI_GOT_BITMASK) { + fbinfo = &efi_framebuffer_format_map[info->pixel_format]; vesa->red_mask_size = fbinfo->red.size; vesa->red_mask_pos = fbinfo->red.pos; vesa->green_mask_size = fbinfo->green.size; @@ -108,29 +139,29 @@ static int save_vesa_mode(struct vesa_mode_info *vesa) vesa->reserved_mask_pos = fbinfo->rsvd.pos;
vesa->bits_per_pixel = 32; - vesa->bytes_per_scanline = mode->info->pixels_per_scanline * 4; - } else if (mode->info->pixel_format == EFI_GOT_BITMASK) { - efi_find_pixel_bits(mode->info->pixel_bitmask[0], + vesa->bytes_per_scanline = info->pixels_per_scanline * 4; + } else if (info->pixel_format == EFI_GOT_BITMASK) { + efi_find_pixel_bits(info->pixel_bitmask[0], &vesa->red_mask_pos, &vesa->red_mask_size); - efi_find_pixel_bits(mode->info->pixel_bitmask[1], + efi_find_pixel_bits(info->pixel_bitmask[1], &vesa->green_mask_pos, &vesa->green_mask_size); - efi_find_pixel_bits(mode->info->pixel_bitmask[2], + efi_find_pixel_bits(info->pixel_bitmask[2], &vesa->blue_mask_pos, &vesa->blue_mask_size); - efi_find_pixel_bits(mode->info->pixel_bitmask[3], + efi_find_pixel_bits(info->pixel_bitmask[3], &vesa->reserved_mask_pos, &vesa->reserved_mask_size); vesa->bits_per_pixel = vesa->red_mask_size + vesa->green_mask_size + vesa->blue_mask_size + vesa->reserved_mask_size; - vesa->bytes_per_scanline = (mode->info->pixels_per_scanline * + vesa->bytes_per_scanline = (info->pixels_per_scanline * vesa->bits_per_pixel) / 8; } else { debug("efi set unknown framebuffer format: %d\n", - mode->info->pixel_format); + info->pixel_format); return -EINVAL; }

The mode info is currently not initialised for the app. Fix this by returning it from the function.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
drivers/video/efi.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/video/efi.c b/drivers/video/efi.c index fc37a68b376..0479f207032 100644 --- a/drivers/video/efi.c +++ b/drivers/video/efi.c @@ -56,10 +56,12 @@ static void efi_find_pixel_bits(u32 mask, u8 *pos, u8 *size) * Gets info from the graphics-output protocol * * @vesa: Place to put the mode information + * @infop: Returns a pointer to the mode info * Returns: 0 if OK, -ENOSYS if boot services are not available, -ENOTSUPP if * the protocol is not supported by EFI */ -static int get_mode_info(struct vesa_mode_info *vesa) +static int get_mode_info(struct vesa_mode_info *vesa, + struct efi_gop_mode_info **infop) { efi_guid_t efi_gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; struct efi_boot_services *boot = efi_get_boot(); @@ -77,6 +79,7 @@ static int get_mode_info(struct vesa_mode_info *vesa) vesa->phys_base_ptr = mode->fb_base; vesa->x_resolution = mode->info->width; vesa->y_resolution = mode->info->height; + *infop = mode->info;
return 0; } @@ -118,7 +121,7 @@ static int save_vesa_mode(struct vesa_mode_info *vesa) int ret;
if (IS_ENABLED(CONFIG_EFI_APP)) - ret = get_mode_info(vesa); + ret = get_mode_info(vesa, &info); else ret = get_mode_from_entry(vesa, &info); if (ret) {

The current vesa structure only provides a 32-bit value for the frame buffer. Many modern machines use an address outside the range.
It is still useful to have this common struct, but add a separate frame-buffer address as well.
Add a comment for vesa_setup_video_priv() while we are here.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v3: - Use Returns instead of @return
arch/x86/lib/fsp/fsp_graphics.c | 2 +- drivers/pci/pci_rom.c | 10 ++++++---- drivers/video/coreboot.c | 2 +- drivers/video/efi.c | 34 +++++++++++++++++++++------------ include/vesa.h | 16 +++++++++++++++- 5 files changed, 45 insertions(+), 19 deletions(-)
diff --git a/arch/x86/lib/fsp/fsp_graphics.c b/arch/x86/lib/fsp/fsp_graphics.c index b07c666caf7..2bcc49f6051 100644 --- a/arch/x86/lib/fsp/fsp_graphics.c +++ b/arch/x86/lib/fsp/fsp_graphics.c @@ -106,7 +106,7 @@ static int fsp_video_probe(struct udevice *dev) vesa->phys_base_ptr = dm_pci_read_bar32(dev, 2); gd->fb_base = vesa->phys_base_ptr;
- ret = vesa_setup_video_priv(vesa, uc_priv, plat); + ret = vesa_setup_video_priv(vesa, vesa->phys_base_ptr, uc_priv, plat); if (ret) goto err;
diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index 47b6e6e5bcf..f0dfe631490 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -325,7 +325,7 @@ err: return ret; }
-int vesa_setup_video_priv(struct vesa_mode_info *vesa, +int vesa_setup_video_priv(struct vesa_mode_info *vesa, u64 fb, struct video_priv *uc_priv, struct video_uc_plat *plat) { @@ -348,9 +348,9 @@ int vesa_setup_video_priv(struct vesa_mode_info *vesa,
/* Use double buffering if enabled */ if (IS_ENABLED(CONFIG_VIDEO_COPY) && plat->base) - plat->copy_base = vesa->phys_base_ptr; + plat->copy_base = fb; else - plat->base = vesa->phys_base_ptr; + plat->base = fb; log_debug("base = %lx, copy_base = %lx\n", plat->base, plat->copy_base); plat->size = vesa->bytes_per_scanline * vesa->y_resolution;
@@ -377,7 +377,9 @@ int vesa_setup_video(struct udevice *dev, int (*int15_handler)(void)) return ret; }
- ret = vesa_setup_video_priv(&mode_info.vesa, uc_priv, plat); + ret = vesa_setup_video_priv(&mode_info.vesa, + mode_info.vesa.phys_base_ptr, uc_priv, + plat); if (ret) { if (ret == -ENFILE) { /* diff --git a/drivers/video/coreboot.c b/drivers/video/coreboot.c index d2d87c75c89..c586475e41e 100644 --- a/drivers/video/coreboot.c +++ b/drivers/video/coreboot.c @@ -57,7 +57,7 @@ static int coreboot_video_probe(struct udevice *dev) goto err; }
- ret = vesa_setup_video_priv(vesa, uc_priv, plat); + ret = vesa_setup_video_priv(vesa, vesa->phys_base_ptr, uc_priv, plat); if (ret) { ret = log_msg_ret("setup", ret); goto err; diff --git a/drivers/video/efi.c b/drivers/video/efi.c index 0479f207032..169637c2882 100644 --- a/drivers/video/efi.c +++ b/drivers/video/efi.c @@ -5,6 +5,8 @@ * EFI framebuffer driver based on GOP */
+#define LOG_CATEGORY LOGC_EFI + #include <common.h> #include <dm.h> #include <efi_api.h> @@ -56,11 +58,12 @@ static void efi_find_pixel_bits(u32 mask, u8 *pos, u8 *size) * Gets info from the graphics-output protocol * * @vesa: Place to put the mode information + * @fbp: Returns the address of the frame buffer * @infop: Returns a pointer to the mode info * Returns: 0 if OK, -ENOSYS if boot services are not available, -ENOTSUPP if * the protocol is not supported by EFI */ -static int get_mode_info(struct vesa_mode_info *vesa, +static int get_mode_info(struct vesa_mode_info *vesa, u64 *fbp, struct efi_gop_mode_info **infop) { efi_guid_t efi_gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; @@ -74,9 +77,13 @@ static int get_mode_info(struct vesa_mode_info *vesa, ret = boot->locate_protocol(&efi_gop_guid, NULL, (void **)&gop); if (ret) return log_msg_ret("prot", -ENOTSUPP); - mode = gop->mode; + log_debug("maxmode %u, mode %u, info %p, size %lx, fb %lx, fb_size %lx\n", + mode->max_mode, mode->mode, mode->info, mode->info_size, + (ulong)mode->fb_base, (ulong)mode->fb_size); + vesa->phys_base_ptr = mode->fb_base; + *fbp = mode->fb_base; vesa->x_resolution = mode->info->width; vesa->y_resolution = mode->info->height; *infop = mode->info; @@ -91,10 +98,11 @@ static int get_mode_info(struct vesa_mode_info *vesa, * it into a vesa structure. It also returns the mode information. * * @vesa: Place to put the mode information + * @fbp: Returns the address of the frame buffer * @infop: Returns a pointer to the mode info * Returns: 0 if OK, -ve on error */ -static int get_mode_from_entry(struct vesa_mode_info *vesa, +static int get_mode_from_entry(struct vesa_mode_info *vesa, u64 *fbp, struct efi_gop_mode_info **infop) { struct efi_gop_mode *mode; @@ -107,6 +115,7 @@ static int get_mode_from_entry(struct vesa_mode_info *vesa, return ret; } vesa->phys_base_ptr = mode->fb_base; + *fbp = mode->fb_base; vesa->x_resolution = mode->info->width; vesa->y_resolution = mode->info->height; *infop = mode->info; @@ -114,16 +123,17 @@ static int get_mode_from_entry(struct vesa_mode_info *vesa, return 0; }
-static int save_vesa_mode(struct vesa_mode_info *vesa) +static int save_vesa_mode(struct vesa_mode_info *vesa, u64 *fbp) { const struct efi_framebuffer *fbinfo; struct efi_gop_mode_info *info; int ret;
+ printf("start\n"); if (IS_ENABLED(CONFIG_EFI_APP)) - ret = get_mode_info(vesa, &info); + ret = get_mode_info(vesa, fbp, &info); else - ret = get_mode_from_entry(vesa, &info); + ret = get_mode_from_entry(vesa, fbp, &info); if (ret) { printf("EFI graphics output protocol not found (err=%dE)\n", ret); @@ -163,8 +173,7 @@ static int save_vesa_mode(struct vesa_mode_info *vesa) vesa->bytes_per_scanline = (info->pixels_per_scanline * vesa->bits_per_pixel) / 8; } else { - debug("efi set unknown framebuffer format: %d\n", - info->pixel_format); + log_err("Unknown framebuffer format: %d\n", info->pixel_format); return -EINVAL; }
@@ -176,19 +185,20 @@ static int efi_video_probe(struct udevice *dev) struct video_uc_plat *plat = dev_get_uclass_plat(dev); struct video_priv *uc_priv = dev_get_uclass_priv(dev); struct vesa_mode_info *vesa = &mode_info.vesa; + u64 fb; int ret;
/* Initialize vesa_mode_info structure */ - ret = save_vesa_mode(vesa); + ret = save_vesa_mode(vesa, &fb); if (ret) goto err;
- ret = vesa_setup_video_priv(vesa, uc_priv, plat); + ret = vesa_setup_video_priv(vesa, fb, uc_priv, plat); if (ret) goto err;
- printf("Video: %dx%dx%d\n", uc_priv->xsize, uc_priv->ysize, - vesa->bits_per_pixel); + printf("Video: %dx%dx%d @ %lx\n", uc_priv->xsize, uc_priv->ysize, + vesa->bits_per_pixel, (ulong)fb);
return 0;
diff --git a/include/vesa.h b/include/vesa.h index a42c1796863..9285bfa921a 100644 --- a/include/vesa.h +++ b/include/vesa.h @@ -108,7 +108,21 @@ extern struct vesa_state mode_info;
struct video_priv; struct video_uc_plat; -int vesa_setup_video_priv(struct vesa_mode_info *vesa, + +/** + * vesa_setup_video_priv() - Set up a video device using VESA information + * + * The vesa struct is used by various x86 drivers, so this is a common function + * to use it to set up the video. + * + * @vesa: Vesa information to use (vesa->phys_base_ptr is ignored) + * @fb: Frame buffer address (since vesa->phys_base_ptr is only 32 bits) + * @uc_priv: Video device's uclass-private information + * @plat: Video devices's uclass-private platform data + * Returns: 0 if OK, -ENXIO if the x resolution is 0, -EEPROTONOSUPPORT if the + * pixel format is not supported + */ +int vesa_setup_video_priv(struct vesa_mode_info *vesa, u64 fb, struct video_priv *uc_priv, struct video_uc_plat *plat); int vesa_setup_video(struct udevice *dev, int (*int15_handler)(void));

Add the timer and vendor/model information.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v3: - Show the CPU vendor name also
arch/x86/lib/bdinfo.c | 6 ++++++ cmd/bdinfo.c | 5 +++++ include/init.h | 3 +++ 3 files changed, 14 insertions(+)
diff --git a/arch/x86/lib/bdinfo.c b/arch/x86/lib/bdinfo.c index 0cb79b01bd3..15390070fe8 100644 --- a/arch/x86/lib/bdinfo.c +++ b/arch/x86/lib/bdinfo.c @@ -8,6 +8,7 @@ #include <common.h> #include <efi.h> #include <init.h> +#include <asm/cpu.h> #include <asm/efi.h> #include <asm/global_data.h>
@@ -16,6 +17,11 @@ DECLARE_GLOBAL_DATA_PTR; void arch_print_bdinfo(void) { bdinfo_print_num_l("prev table", gd->arch.table); + bdinfo_print_num_l("clock_rate", gd->arch.clock_rate); + bdinfo_print_num_l("tsc_base", gd->arch.tsc_base); + bdinfo_print_num_l("vendor", gd->arch.x86_vendor); + bdinfo_print_str(" name", cpu_vendor_name(gd->arch.x86_vendor)); + bdinfo_print_num_l("model", gd->arch.x86_model);
if (IS_ENABLED(CONFIG_EFI_STUB)) efi_show_bdinfo(); diff --git a/cmd/bdinfo.c b/cmd/bdinfo.c index bf002f84475..8ae7fb35fe9 100644 --- a/cmd/bdinfo.c +++ b/cmd/bdinfo.c @@ -26,6 +26,11 @@ void bdinfo_print_size(const char *name, uint64_t size) print_size(size, "\n"); }
+void bdinfo_print_str(const char *name, const char *str) +{ + printf("%-12s= %s\n", name, str); +} + void bdinfo_print_num_l(const char *name, ulong value) { printf("%-12s= 0x%0*lx\n", name, 2 * (int)sizeof(value), value); diff --git a/include/init.h b/include/init.h index 699dc2482c0..88730816851 100644 --- a/include/init.h +++ b/include/init.h @@ -353,6 +353,9 @@ void relocate_code(ulong start_addr_sp, struct global_data *new_gd, void bdinfo_print_num_l(const char *name, ulong value); void bdinfo_print_num_ll(const char *name, unsigned long long value);
+/* Print a string value (for use in arch_print_bdinfo()) */ +void bdinfo_print_str(const char *name, const char *str); + /* Print a clock speed in MHz */ void bdinfo_print_mhz(const char *name, unsigned long hz);

It is not yet clear how to read the timer via EFI. The current value seems much too high on a Framework laptop I tried. Adjust it to a lower hard-coded value for now.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v3: - Add a comment about the value
drivers/timer/tsc_timer.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/drivers/timer/tsc_timer.c b/drivers/timer/tsc_timer.c index 192c7b71a5a..f86a0b86921 100644 --- a/drivers/timer/tsc_timer.c +++ b/drivers/timer/tsc_timer.c @@ -404,6 +404,15 @@ static void tsc_timer_ensure_setup(bool early) if (!gd->arch.clock_rate) { unsigned long fast_calibrate;
+ /** + * There is no obvious way to obtain this information from EFI + * boot services. This value was measured on a Framework Laptop + * which has a 12th Gen Intel Core + */ + if (IS_ENABLED(CONFIG_EFI_APP)) { + fast_calibrate = 2750; + goto done; + } fast_calibrate = native_calibrate_tsc(); if (fast_calibrate) goto done;

Add support for this to EFI in case it becomes useful. At present it just slows things down. You can enable CONFIG_VIDEO_COPY to turn it on.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v3: - Add a comment about the fallback
Changes in v2: - Obtain copy framebuffer size from EFI instead of using a fixed value - Dropping debugging printf() - Use new bootph-xxx tag
arch/x86/dts/efi-x86_app.dts | 1 + drivers/video/efi.c | 26 +++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/arch/x86/dts/efi-x86_app.dts b/arch/x86/dts/efi-x86_app.dts index 6d843a9820b..59e2e402d5e 100644 --- a/arch/x86/dts/efi-x86_app.dts +++ b/arch/x86/dts/efi-x86_app.dts @@ -27,6 +27,7 @@ }; efi-fb { compatible = "efi-fb"; + bootph-some-ram; };
}; diff --git a/drivers/video/efi.c b/drivers/video/efi.c index 169637c2882..28ac15ff61b 100644 --- a/drivers/video/efi.c +++ b/drivers/video/efi.c @@ -129,7 +129,6 @@ static int save_vesa_mode(struct vesa_mode_info *vesa, u64 *fbp) struct efi_gop_mode_info *info; int ret;
- printf("start\n"); if (IS_ENABLED(CONFIG_EFI_APP)) ret = get_mode_info(vesa, fbp, &info); else @@ -207,6 +206,30 @@ err: return ret; }
+static int efi_video_bind(struct udevice *dev) +{ + if (IS_ENABLED(CONFIG_VIDEO_COPY)) { + struct video_uc_plat *plat = dev_get_uclass_plat(dev); + struct vesa_mode_info vesa; + int ret; + u64 fb; + + /* + * Initialise vesa_mode_info structure so we can figure out the + * required framebuffer size. If something goes wrong, just do + * without a copy framebuffer + */ + ret = save_vesa_mode(&vesa, &fb); + if (!ret) { + /* this is not reached if the EFI call failed */ + plat->copy_size = vesa.bytes_per_scanline * + vesa.y_resolution; + } + } + + return 0; +} + static const struct udevice_id efi_video_ids[] = { { .compatible = "efi-fb" }, { } @@ -216,5 +239,6 @@ U_BOOT_DRIVER(efi_video) = { .name = "efi_video", .id = UCLASS_VIDEO, .of_match = efi_video_ids, + .bind = efi_video_bind, .probe = efi_video_probe, };

At present it is not possible for the video driver to use a pre-allocated frame buffer (such as is done with EFI) with the copy framebuffer. This can be useful to speed up the display.
Adjust the implementation so that copy_size can be set to the required size, with this being allocated if the normal framebuffer size is 0.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
drivers/video/video-uclass.c | 32 ++++++++++++++++++++++++-------- include/video.h | 2 ++ 2 files changed, 26 insertions(+), 8 deletions(-)
diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c index ab482f11e5d..da89f431441 100644 --- a/drivers/video/video-uclass.c +++ b/drivers/video/video-uclass.c @@ -78,24 +78,40 @@ void video_set_flush_dcache(struct udevice *dev, bool flush) priv->flush_dcache = flush; }
+static ulong alloc_fb_(ulong align, ulong size, ulong *addrp) +{ + ulong base; + + align = align ? align : 1 << 20; + base = *addrp - size; + base &= ~(align - 1); + size = *addrp - base; + *addrp = base; + + return size; +} + static ulong alloc_fb(struct udevice *dev, ulong *addrp) { struct video_uc_plat *plat = dev_get_uclass_plat(dev); - ulong base, align, size; + ulong size; + + if (!plat->size) { + if (IS_ENABLED(CONFIG_VIDEO_COPY) && plat->copy_size) { + size = alloc_fb_(plat->align, plat->copy_size, addrp); + plat->copy_base = *addrp; + return size; + }
- if (!plat->size) return 0; + }
/* Allow drivers to allocate the frame buffer themselves */ if (plat->base) return 0;
- align = plat->align ? plat->align : 1 << 20; - base = *addrp - plat->size; - base &= ~(align - 1); - plat->base = base; - size = *addrp - base; - *addrp = base; + size = alloc_fb_(plat->align, plat->size, addrp); + plat->base = *addrp;
return size; } diff --git a/include/video.h b/include/video.h index 3f67a93bc93..4d99e5dc27f 100644 --- a/include/video.h +++ b/include/video.h @@ -24,6 +24,7 @@ struct udevice; * @base: Base address of frame buffer, 0 if not yet known * @copy_base: Base address of a hardware copy of the frame buffer. See * CONFIG_VIDEO_COPY. + * @copy_size: Size of copy framebuffer, used if @size is 0 * @hide_logo: Hide the logo (used for testing) */ struct video_uc_plat { @@ -31,6 +32,7 @@ struct video_uc_plat { uint size; ulong base; ulong copy_base; + ulong copy_size; bool hide_logo; };

If the copy framebuffer is enabled, show its size.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v2)
Changes in v2: - Add new patch to show the size of the copy framebuffer with bdinfo
cmd/bdinfo.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/cmd/bdinfo.c b/cmd/bdinfo.c index 8ae7fb35fe9..f709904c516 100644 --- a/cmd/bdinfo.c +++ b/cmd/bdinfo.c @@ -88,11 +88,15 @@ static void show_video_info(void) device_active(dev) ? "" : "in"); if (device_active(dev)) { struct video_priv *upriv = dev_get_uclass_priv(dev); + struct video_uc_plat *plat = dev_get_uclass_plat(dev);
bdinfo_print_num_ll("FB base", (ulong)upriv->fb); - if (upriv->copy_fb) + if (upriv->copy_fb) { bdinfo_print_num_ll("FB copy", (ulong)upriv->copy_fb); + bdinfo_print_num_l(" copy size", + plat->copy_size); + } printf("%-12s= %dx%dx%d\n", "FB size", upriv->xsize, upriv->ysize, 1 << upriv->bpix); }

When running with video enabled, the pre-relocation output of U-Boot is currently lost. Add a -serial flag to show it on the terminal.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
scripts/build-efi.sh | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/scripts/build-efi.sh b/scripts/build-efi.sh index bc9aeebbf4f..46c28807ef1 100755 --- a/scripts/build-efi.sh +++ b/scripts/build-efi.sh @@ -96,6 +96,8 @@ run_qemu() { fi if [[ -n "${serial}" ]]; then extra="-display none -serial mon:stdio" + else + extra="-serial mon:stdio" fi echo "Running ${qemu}" # Use 512MB since U-Boot EFI likes to have 256MB to play with

There are two functions for positioning the cursor on the console. Remove one of them.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
drivers/video/vidconsole-uclass.c | 44 +++++++------------------------ 1 file changed, 10 insertions(+), 34 deletions(-)
diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c index 72a13d30527..9f8b8ebe8ac 100644 --- a/drivers/video/vidconsole-uclass.c +++ b/drivers/video/vidconsole-uclass.c @@ -126,26 +126,14 @@ void vidconsole_set_cursor_pos(struct udevice *dev, int x, int y) priv->ycur = y; }
-/** - * set_cursor_position() - set cursor position - * - * @priv: private data of the video console - * @row: new row - * @col: new column - */ -static void set_cursor_position(struct vidconsole_priv *priv, int row, int col) +void vidconsole_position_cursor(struct udevice *dev, uint col, uint row) { - /* - * Ensure we stay in the bounds of the screen. - */ - if (row >= priv->rows) - row = priv->rows - 1; - if (col >= priv->cols) - col = priv->cols - 1; - - priv->ycur = row * priv->y_charsize; - priv->xcur_frac = priv->xstart_frac + - VID_TO_POS(col * priv->x_charsize); + struct vidconsole_priv *priv = dev_get_uclass_priv(dev); + short x, y; + + x = min_t(short, col, priv->cols - 1) * priv->x_charsize; + y = min_t(short, row, priv->rows - 1) * priv->y_charsize; + vidconsole_set_cursor_pos(dev, x, y); }
/** @@ -192,7 +180,7 @@ static void vidconsole_escape_char(struct udevice *dev, char ch) int row = priv->row_saved; int col = priv->col_saved;
- set_cursor_position(priv, row, col); + vidconsole_position_cursor(dev, col, row); priv->escape = 0; return; } @@ -254,7 +242,7 @@ static void vidconsole_escape_char(struct udevice *dev, char ch) if (row < 0) row = 0; /* Right and bottom overflows are handled in the callee. */ - set_cursor_position(priv, row, col); + vidconsole_position_cursor(dev, col, row); break; } case 'H': @@ -278,7 +266,7 @@ static void vidconsole_escape_char(struct udevice *dev, char ch) if (col) --col;
- set_cursor_position(priv, row, col); + vidconsole_position_cursor(dev, col, row);
break; } @@ -644,15 +632,3 @@ int vidconsole_memmove(struct udevice *dev, void *dst, const void *src, return vidconsole_sync_copy(dev, dst, dst + size); } #endif - -void vidconsole_position_cursor(struct udevice *dev, unsigned col, unsigned row) -{ - struct vidconsole_priv *priv = dev_get_uclass_priv(dev); - struct udevice *vid_dev = dev->parent; - struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev); - short x, y; - - x = min_t(short, col * priv->x_charsize, vid_priv->xsize - 1); - y = min_t(short, row * priv->y_charsize, vid_priv->ysize - 1); - vidconsole_set_cursor_pos(dev, x, y); -}

It is better to clear the console device rather than the video device, since the console has the text display. We also need to reset the cursor position with the console, but not with the video device.
Add a new function to handle this and update the 'cls' command to use it.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
cmd/cls.c | 12 ++++++++---- drivers/video/vidconsole-uclass.c | 12 ++++++++++++ include/video_console.h | 9 +++++++++ 3 files changed, 29 insertions(+), 4 deletions(-)
diff --git a/cmd/cls.c b/cmd/cls.c index 40a32eeab63..073ba5a6c86 100644 --- a/cmd/cls.c +++ b/cmd/cls.c @@ -8,7 +8,7 @@ #include <common.h> #include <command.h> #include <dm.h> -#include <video.h> +#include <video_console.h>
#define CSI "\x1b["
@@ -19,12 +19,16 @@ static int do_video_clear(struct cmd_tbl *cmdtp, int flag, int argc,
/* Send clear screen and home */ printf(CSI "2J" CSI "1;1H"); - if (IS_ENABLED(CONFIG_VIDEO) && !IS_ENABLED(CONFIG_VIDEO_ANSI)) { - if (uclass_first_device_err(UCLASS_VIDEO, &dev)) + if (IS_ENABLED(CONFIG_VIDEO_ANSI)) + return 0; + + if (IS_ENABLED(CONFIG_VIDEO)) { + if (uclass_first_device_err(UCLASS_VIDEO_CONSOLE, &dev)) return CMD_RET_FAILURE; - if (video_clear(dev)) + if (vidconsole_clear_and_reset(dev)) return CMD_RET_FAILURE; } + return CMD_RET_SUCCESS; }
diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c index 9f8b8ebe8ac..1bb36bd66c7 100644 --- a/drivers/video/vidconsole-uclass.c +++ b/drivers/video/vidconsole-uclass.c @@ -632,3 +632,15 @@ int vidconsole_memmove(struct udevice *dev, void *dst, const void *src, return vidconsole_sync_copy(dev, dst, dst + size); } #endif + +int vidconsole_clear_and_reset(struct udevice *dev) +{ + int ret; + + ret = video_clear(dev_get_parent(dev)); + if (ret) + return ret; + vidconsole_position_cursor(dev, 0, 0); + + return 0; +} diff --git a/include/video_console.h b/include/video_console.h index 9d2c0f210e4..aebf1d5eb99 100644 --- a/include/video_console.h +++ b/include/video_console.h @@ -276,6 +276,15 @@ int vidconsole_put_string(struct udevice *dev, const char *str); void vidconsole_position_cursor(struct udevice *dev, unsigned col, unsigned row);
+/** + * vidconsole_clear_and_reset() - Clear the console and reset the cursor + * + * The cursor is placed at the start of the console + * + * @dev: vidconsole device to adjust + */ +int vidconsole_clear_and_reset(struct udevice *dev); + /** * vidconsole_set_cursor_pos() - set cursor position *

Add these options to provide some performance measurement, see cache status and slightly speed up the appallingly slow console.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
configs/efi-x86_app64_defconfig | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/configs/efi-x86_app64_defconfig b/configs/efi-x86_app64_defconfig index 605d49ff8cb..dae48840493 100644 --- a/configs/efi-x86_app64_defconfig +++ b/configs/efi-x86_app64_defconfig @@ -22,6 +22,7 @@ CONFIG_SYS_PBSIZE=532 # CONFIG_CMD_BOOTM is not set CONFIG_CMD_PART=y # CONFIG_CMD_NET is not set +CONFIG_CMD_CACHE=y CONFIG_CMD_TIME=y CONFIG_CMD_EXT2=y CONFIG_CMD_EXT4=y @@ -39,7 +40,9 @@ CONFIG_BOOTFILE="bzImage" CONFIG_USE_ROOTPATH=y CONFIG_REGMAP=y CONFIG_SYSCON=y +CONFIG_CONSOLE_SCROLL_LINES=5 # CONFIG_REGEX is not set +CONFIG_CMD_DHRYSTONE=y # CONFIG_GZIP is not set CONFIG_EFI=y CONFIG_EFI_APP_64BIT=y

The cls command is broken. Previous discussion about this was at [1] and [2]. For now, add a note to the source code.
[1] https://patchwork.ozlabs.org/project/uboot/patch/ 20221022092058.106052-1-heinrich.schuchardt@canonical.com/ [2] https://patchwork.ozlabs.org/project/uboot/patch/ 20230106145243.411626-12-sjg@chromium.org/
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
cmd/cls.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/cmd/cls.c b/cmd/cls.c index 073ba5a6c86..1125a3f81bb 100644 --- a/cmd/cls.c +++ b/cmd/cls.c @@ -17,7 +17,13 @@ static int do_video_clear(struct cmd_tbl *cmdtp, int flag, int argc, { __maybe_unused struct udevice *dev;
- /* Send clear screen and home */ + /* + * Send clear screen and home + * + * FIXME(Heinrich Schuchardt xypron.glpk@gmx.de): This should go + * through an API and only be written to serial terminals, not video + * displays + */ printf(CSI "2J" CSI "1;1H"); if (IS_ENABLED(CONFIG_VIDEO_ANSI)) return 0;
participants (1)
-
Simon Glass