On Sun, Apr 14, 2024 at 10:30:55AM +0000, Riku Viitanen via SeaBIOS wrote:
> VGAROMs on MXM graphics cards need certain int15h functions present
> to function properly.
> 
> On HP EliteBook 8560w with coreboot and Quadro 2000M, this warning
> is displayed for 30 seconds, making every boot extremely slow:
> 
>     ERROR: Valid MXM Structure not found
>     POST halted for 30 seconds, P-state limited to P10...
> 
> This patch implements the minimum functionality to get rid of it: the
> functions 0 and 1, version 3.0 of the specification [1]. Older version
> 2.1 is not implemented.
> 
> Functions are enabled only if romfile "mxm-30-sis" exists. These functions
> are specific to the MXM revision, but not the board or GPU. Some boards
> might require more of the optional functions to be implemented, however.
> 
> - Function 0 returns information about supported functions and revision.
> 
> - Function 1 returns a pointer to a MXM configuration structure in low
> memory. This is copied from romfile "mxm-30-sis". It can be extracted
> from vendor BIOS, by using this same interrupt. I wrote a tool [2] to do
> that from Linux.
> 
> TEST: HP EliteBook 8560w boots without error and delay, graphics work.
> 
> [1]: MXM Graphics Module Software Specification Version 3.0, Revision 1.1
> [2]: https://codeberg.org/Riku_V/mxmdump/

Thanks.  In general it looks good to me.  I have a few minor comments.

> 
> Signed-off-by: Riku Viitanen riku.viita...@protonmail.com
> ---
>  src/vgahooks.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 79 insertions(+)
> 
> diff --git a/src/vgahooks.c b/src/vgahooks.c
> index 1f149532..6adf5b9b 100644
> --- a/src/vgahooks.c
> +++ b/src/vgahooks.c
> @@ -11,13 +11,16 @@
>  #include "hw/pcidevice.h" // pci_find_device
>  #include "hw/pci_ids.h" // PCI_VENDOR_ID_VIA
>  #include "hw/pci_regs.h" // PCI_VENDOR_ID
> +#include "malloc.h" // malloc_low
>  #include "output.h" // dprintf
> +#include "romfile.h" // struct romfile_s, romfile_find
>  #include "string.h" // strcmp
>  #include "util.h" // handle_155f, handle_157f
>  
>  #define VH_VIA 1
>  #define VH_INTEL 2
>  #define VH_SMI 3
> +#define VH_MXM30 4
>  
>  int VGAHookHandlerType VARFSEG;
>  
> @@ -296,6 +299,77 @@ winent_mb6047_setup(struct pci_device *pci)
>      SmiBootDisplay = 0x02;
>  }
>  
> +/****************************************************************
> + * MXM 3.0 hooks
> + ****************************************************************/
> +
> +void *MXM30SIS VARFSEG;
> +
> +/* Function 0: Return Specification Support Level */
> +static void
> +mxm30_F00(struct bregs *regs)
> +{
> +    regs->ax = 0x005f; /* Success */
> +    regs->bl = 0x30; /* MXM version 3.0 */
> +    regs->cx = (1<<0) | (1<<1); /* Supported functions */
> +    set_success(regs);
> +}
> +
> +/* Function 1: Return Pointer to MXM System Information Structure */
> +static void
> +mxm30_F01(struct bregs *regs)
> +{
> +    switch (regs->cx) {
> +    case 0x0030:
> +        regs->ax = 0x005f; /* Success */
> +        regs->es = (u32)GET_GLOBAL(MXM30SIS)/16;
> +        regs->di = (u32)GET_GLOBAL(MXM30SIS)%16;

This should use SEG_LOW and LOWFLAT2LOW(MXM30SIS).

> +        set_success(regs);
> +        break;
> +    default:
> +        handle_155fXX(regs);
> +        break;
> +    }
> +}
> +
> +static void
> +mxm30_155f80(struct bregs *regs)
> +{
> +    switch (regs->bx) {
> +    case 0xff00: mxm30_F00(regs); break;
> +    case 0xff01: mxm30_F01(regs); break;
> +    default:     handle_155fXX(regs); break;
> +    }
> +}
> +
> +static void
> +mxm30_155f(struct bregs *regs)
> +{
> +    switch (regs->al) {
> +    case 0x80: mxm30_155f80(regs); break;
> +    default:   handle_155fXX(regs); break;
> +    }
> +}
> +
> +static void
> +mxm30_setup(struct romfile_s *sis_file)
> +{
> +    /* Load MXM System Information Structure into low memory */
> +    MXM30SIS = malloc_low(sis_file->size);

This code does not check if sis_file is NULL, which could lead to
memory corruption.

Probably best to use romfile_loadfile(), check for non-null, and then
malloc_low(), manual memcpy(), and free() of the temporary space.  As
it's preferable to avoid calls to free() on malloc_low() allocations -
as that can lead to memory fragmentation of the scarce "low" region.

> +    if (!MXM30SIS) {
> +        warn_noalloc();
> +        return;
> +    }
> +    int ret = sis_file->copy(sis_file, MXM30SIS, sis_file->size);
> +    if (ret < 0) {
> +        free(MXM30SIS);
> +        MXM30SIS = NULL;
> +        return;
> +    }
> +
> +    VGAHookHandlerType = VH_MXM30;
> +}
> +
>  /****************************************************************
>   * Entry and setup
>   ****************************************************************/
> @@ -313,6 +387,7 @@ handle_155f(struct bregs *regs)
>      switch (htype) {
>      case VH_VIA:   via_155f(regs); break;
>      case VH_INTEL: intel_155f(regs); break;
> +    case VH_MXM30: mxm30_155f(regs); break;
>      default:       handle_155fXX(regs); break;
>      }
>  }
> @@ -340,6 +415,8 @@ vgahook_setup(struct pci_device *pci)
>      if (!CONFIG_VGAHOOKS)
>          return;
>  
> +    struct romfile_s *mxm30sis = romfile_find("mxm-30-sis");
> +
>      if (strcmp(CBvendor, "KONTRON") == 0 && strcmp(CBpart, "986LCD-M") == 0)
>          kontron_setup(pci);
>      else if (strcmp(CBvendor, "GETAC") == 0 && strcmp(CBpart, "P470") == 0)
> @@ -352,4 +429,6 @@ vgahook_setup(struct pci_device *pci)
>          via_setup(pci);
>      else if (pci->vendor == PCI_VENDOR_ID_INTEL)
>          intel_setup(pci);
> +    else if (mxm30sis != NULL)
> +        mxm30_setup(mxm30sis);

I think it would be preferable if mxm_setup() was passed the pci
device for uniformity, and have mxm_setup() call romfile_xxx() itself.

-Kevin

>  }
> -- 
> 2.44.0
> 
> _______________________________________________
> SeaBIOS mailing list -- seabios@seabios.org
> To unsubscribe send an email to seabios-le...@seabios.org
_______________________________________________
SeaBIOS mailing list -- seabios@seabios.org
To unsubscribe send an email to seabios-le...@seabios.org

Reply via email to