|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v4 2/8] x86/boot: obtain video info from boot loader
On Thu, Mar 31, 2022 at 11:45:02AM +0200, Jan Beulich wrote:
> With MB2 the boot loader may provide this information, allowing us to
> obtain it without needing to enter real mode (assuming we don't need to
> set a new mode from "vga=", but can instead inherit the one the
> bootloader may have established).
>
> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
> ---
> v4: Re-base.
> v3: Re-base.
> v2: New.
>
> --- a/xen/arch/x86/boot/defs.h
> +++ b/xen/arch/x86/boot/defs.h
> @@ -53,6 +53,7 @@ typedef unsigned int u32;
> typedef unsigned long long u64;
> typedef unsigned int size_t;
> typedef u8 uint8_t;
> +typedef u16 uint16_t;
> typedef u32 uint32_t;
> typedef u64 uint64_t;
>
> --- a/xen/arch/x86/boot/head.S
> +++ b/xen/arch/x86/boot/head.S
> @@ -562,12 +562,18 @@ trampoline_setup:
> mov %esi, sym_esi(xen_phys_start)
> mov %esi, sym_esi(trampoline_xen_phys_start)
>
> - mov sym_esi(trampoline_phys), %ecx
> -
> /* Get bottom-most low-memory stack address. */
> + mov sym_esi(trampoline_phys), %ecx
> add $TRAMPOLINE_SPACE,%ecx
Just for my understanding, since you are already touching the
instruction, why not switch it to a lea like you do below?
Is that because you would also like to take the opportunity to fold
the add into the lea and that would be too much of a change?
>
> +#ifdef CONFIG_VIDEO
> + lea sym_esi(boot_vid_info), %edx
> +#else
> + xor %edx, %edx
> +#endif
> +
> /* Save Multiboot / PVH info struct (after relocation) for later
> use. */
> + push %edx /* Boot video info to be filled from
> MB2. */
> push %ecx /* Bottom-most low-memory stack address.
> */
> push %ebx /* Multiboot / PVH information address.
> */
> push %eax /* Magic number. */
> --- a/xen/arch/x86/boot/reloc.c
> +++ b/xen/arch/x86/boot/reloc.c
> @@ -14,9 +14,10 @@
>
> /*
> * This entry point is entered from xen/arch/x86/boot/head.S with:
> - * - 0x4(%esp) = MAGIC,
> - * - 0x8(%esp) = INFORMATION_ADDRESS,
> - * - 0xc(%esp) = TOPMOST_LOW_MEMORY_STACK_ADDRESS.
> + * - 0x04(%esp) = MAGIC,
> + * - 0x08(%esp) = INFORMATION_ADDRESS,
> + * - 0x0c(%esp) = TOPMOST_LOW_MEMORY_STACK_ADDRESS.
> + * - 0x10(%esp) = BOOT_VIDEO_INFO_ADDRESS.
> */
> asm (
> " .text \n"
> @@ -32,6 +33,39 @@ asm (
> #include "../../../include/xen/kconfig.h"
> #include <public/arch-x86/hvm/start_info.h>
>
> +#ifdef CONFIG_VIDEO
> +# include "video.h"
> +
> +/* VESA control information */
> +struct __packed vesa_ctrl_info {
> + uint8_t signature[4];
> + uint16_t version;
> + uint32_t oem_name;
> + uint32_t capabilities;
> + uint32_t mode_list;
> + uint16_t mem_size;
> + /* We don't use any further fields. */
> +};
> +
> +/* VESA 2.0 mode information */
> +struct vesa_mode_info {
Should we add __packed here just in case further added fields are no
longer naturally aligned? (AFAICT all field right now are aligned to
it's size so there's no need for it).
> + uint16_t attrib;
> + uint8_t window[14]; /* We don't use the individual fields. */
> + uint16_t bytes_per_line;
> + uint16_t width;
> + uint16_t height;
> + uint8_t cell_width;
> + uint8_t cell_height;
> + uint8_t nr_planes;
> + uint8_t depth;
> + uint8_t memory[5]; /* We don't use the individual fields. */
> + struct boot_video_colors colors;
> + uint8_t direct_color;
> + uint32_t base;
> + /* We don't use any further fields. */
> +};
Would it make sense to put those struct definitions in boot/video.h
like you do for boot_video_info?
I also wonder whether you could then hide the #ifdef CONFIG_VIDEO
check inside of the header itself.
> +#endif /* CONFIG_VIDEO */
> +
> #define get_mb2_data(tag, type, member) (((multiboot2_tag_##type##_t
> *)(tag))->member)
> #define get_mb2_string(tag, type, member) ((u32)get_mb2_data(tag, type,
> member))
>
> @@ -146,7 +180,7 @@ static multiboot_info_t *mbi_reloc(u32 m
> return mbi_out;
> }
>
> -static multiboot_info_t *mbi2_reloc(u32 mbi_in)
> +static multiboot_info_t *mbi2_reloc(uint32_t mbi_in, uint32_t video_out)
> {
> const multiboot2_fixed_t *mbi_fix = _p(mbi_in);
> const multiboot2_memory_map_t *mmap_src;
> @@ -154,6 +188,9 @@ static multiboot_info_t *mbi2_reloc(u32
> module_t *mbi_out_mods = NULL;
> memory_map_t *mmap_dst;
> multiboot_info_t *mbi_out;
> +#ifdef CONFIG_VIDEO
> + struct boot_video_info *video = NULL;
> +#endif
> u32 ptr;
> unsigned int i, mod_idx = 0;
>
> @@ -254,17 +291,64 @@ static multiboot_info_t *mbi2_reloc(u32
> ++mod_idx;
> break;
>
> +#ifdef CONFIG_VIDEO
> + case MULTIBOOT2_TAG_TYPE_VBE:
> + if ( video_out )
> + {
> + const struct vesa_ctrl_info *ci;
> + const struct vesa_mode_info *mi;
> +
> + video = _p(video_out);
> + ci = (void *)get_mb2_data(tag, vbe, vbe_control_info);
> + mi = (void *)get_mb2_data(tag, vbe, vbe_mode_info);
> +
> + if ( ci->version >= 0x0200 && (mi->attrib & 0x9b) == 0x9b )
> + {
> + video->capabilities = ci->capabilities;
> + video->lfb_linelength = mi->bytes_per_line;
> + video->lfb_width = mi->width;
> + video->lfb_height = mi->height;
> + video->lfb_depth = mi->depth;
> + video->lfb_base = mi->base;
> + video->lfb_size = ci->mem_size;
> + video->colors = mi->colors;
> + video->vesa_attrib = mi->attrib;
> + }
> +
> + video->vesapm.seg = get_mb2_data(tag, vbe,
> vbe_interface_seg);
> + video->vesapm.off = get_mb2_data(tag, vbe,
> vbe_interface_off);
> + }
> + break;
> +
> + case MULTIBOOT2_TAG_TYPE_FRAMEBUFFER:
> + if ( (get_mb2_data(tag, framebuffer, framebuffer_type) !=
> + MULTIBOOT2_FRAMEBUFFER_TYPE_RGB) )
> + {
> + video_out = 0;
> + video = NULL;
> + }
I'm confused, don't you need to store the information in the
framebuffer tag for use after relocation?
> + break;
> +#endif /* CONFIG_VIDEO */
> +
> case MULTIBOOT2_TAG_TYPE_END:
> - return mbi_out;
> + goto end; /* Cannot "break;" here. */
>
> default:
> break;
> }
>
> + end:
> +
> +#ifdef CONFIG_VIDEO
> + if ( video )
> + video->orig_video_isVGA = 0x23;
I see we use this elsewhere, what's the meaning of this (magic) 0x23?
Thanks, Roger.
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |