Patchwork Various x86emu fixes

login
register
about
Submitter Mark Marshall
Date 2009-10-27 11:34:35
Message ID <hc6lsa$hqg$1@ger.gmane.org>
Download mbox | patch
Permalink /patch/495/
State Accepted
Headers show

Comments

Mark Marshall - 2009-10-27 11:34:35
Below are three small patches, they all seemed useful while I have been 
working with VGA option ROMs.

Thanks for the great work.

MM
Use more care when implimenting the PCI BIOS functions.

The 'CHECK' function seemed to be both wrong code and the wrong
number, so I have just added the corrct code in parallel.

The READ_CONF and WRITE_CONF functions would both do the wrong thing
if the passed in BDF was not found.  We should return and error to the
caller, but not stop running the option ROM.

Signed-off-by: Mark Marshall <mark.marshall@csr.com>
When loading an option ROM use the class stored in the device to
decide whether the option ROM is a special VGA type.

An S3 card that I've got has the wrong class in the VGA BIOS.
(A Stealth 64 DRAM T PCI, from 1994 - BIOS V2.02)

Signed-off-by: Mark Marshall <mark.marshall@csr.com>

Index: src/devices/pci_rom.c
===================================================================
--- src/devices/pci_rom.c	(revision 4822)
+++ src/devices/pci_rom.c	(working copy)
@@ -116,7 +116,10 @@
 
 	rom_size = rom_header->size * 512;
 
-	if (PCI_CLASS_DISPLAY_VGA == rom_data->class_hi) {
+	// We check to see if the device thinks it is a VGA device not
+	// whether the ROM image is for a VGA device because some
+	// devices have a mismatch between the hardware and the ROM
+ 	if (PCI_CLASS_DISPLAY_VGA == (dev->class >> 8)) {
 #if CONFIG_CONSOLE_VGA == 1 && CONFIG_CONSOLE_VGA_MULTI == 0
 		extern device_t vga_pri;	// the primary vga device, defined in device.c
 		if (dev != vga_pri) return NULL; // only one VGA supported
Get the passed in Bus/Device/Function from the correct location on the
stack.

Signed-off-by: Mark Marshall <mark.marshall@csr.com>

Index: util/x86emu/x86_asm.S
===================================================================
--- util/x86emu/x86_asm.S	(revision 4855)
+++ util/x86emu/x86_asm.S	(working copy)
@@ -68,8 +68,8 @@
 
 	/* Get devfn into %ecx */
 	movl    %esp, %ebp
-	// FIXME: Should this function be called with regparm=0?
-	movl    8(%ebp), %ecx
+	/* This function is now called with regparm=0. */
+	movl    36(%ebp), %ecx
 
 	/* Activate the right segment descriptor real mode. */
 	ljmp	$0x28, $RELOCATED(1f)
ron minnich - 2009-10-27 16:51:53
These look really good to me anyway, maybe someone can give them a test?

ron
Mark Marshall - 2009-11-04 18:05:53
Ping.

Mark Marshall wrote:
> Below are three small patches, they all seemed useful while I have been 
> working with VGA option ROMs.
> 
> Thanks for the great work.
> 
> MM
>
Myles Watson - 2009-11-04 18:58:03
> Ping.
The two x86emu fixes look fine to me, but I haven't tested them.

I don't think we should depend on the value from the card.  The point of
that check is to make sure we don't run the wrong types of ROMs.  One way to
work around it would be to correct the VGA BIOS from your card and put it
into CBFS.

Thanks,
Myles
Stefan Reinauer - 2009-11-05 09:18:09
Mark Marshall wrote:
> Ping.
>
> Mark Marshall wrote:
>> Below are three small patches, they all seemed useful while I have
>> been working with VGA option ROMs.
>>
>> Thanks for the great work.
>>
>> MM
>>
>
>
Awesome!

r4909 - r4911
Peter Stuge - 2009-11-06 16:18:57
Myles Watson wrote:
> I don't think we should depend on the value from the card.  The
> point of that check is to make sure we don't run the wrong types of
> ROMs. One way to work around it would be to correct the VGA BIOS
> from your card and put it into CBFS.

Stefan Reinauer wrote:
> > Ping.
> 
> Awesome!

Stefan, what about Myles' comment above? I think it's a good point.


//Peter
Myles Watson - 2009-11-06 16:31:24
On Fri, Nov 6, 2009 at 10:18 AM, Peter Stuge <peter@stuge.se> wrote:

> Myles Watson wrote:
> > I don't think we should depend on the value from the card.  The
> > point of that check is to make sure we don't run the wrong types of
> > ROMs. One way to work around it would be to correct the VGA BIOS
> > from your card and put it into CBFS.
>
> Stefan, what about Myles' comment above? I think it's a good point.
>

We started discussing it off list.  This should catch the list up:

On Thu, Nov 5, 2009 at 11:03 AM, Stefan Reinauer <stepan@coresystems.de>wrote:

> Myles Watson wrote:
> > Did you see my concern with checking the device instead of the ROM?
> >
> > Thanks,
> > Myles
> oops sorry.. I missed that one..
>
No problem.


> Hm.. not sure.. that particular check does not seem to be a consistency
> check but rather a check to determine from which location to run the VGA
> OPROM from... Generally, VGA oproms should run from 0xc0000.
>
Yes.  His card is broken.  I just wanted to make sure the change doesn't
break other things to enable his 10-year-old card.


> Maybe we should add another check whether class of the card and class of
> the device are the same?
>
If we did, that would break his card again.

I guess someone will complain if/when it matters.  I'm not sure what the
"right" thing to do is.

Thanks,
Myles
Mark Marshall - 2009-11-06 18:04:44
Myles Watson wrote:
> 
> 
> On Fri, Nov 6, 2009 at 10:18 AM, Peter Stuge <peter@stuge.se 
> <mailto:peter@stuge.se>> wrote:
> 
>     Myles Watson wrote:
>      > I don't think we should depend on the value from the card.  The
>      > point of that check is to make sure we don't run the wrong types of
>      > ROMs. One way to work around it would be to correct the VGA BIOS
>      > from your card and put it into CBFS.
> 
>     Stefan, what about Myles' comment above? I think it's a good point.
> 
> 
> We started discussing it off list.  This should catch the list up:
> 
> On Thu, Nov 5, 2009 at 11:03 AM, Stefan Reinauer <stepan@coresystems.de 
> <mailto:stepan@coresystems.de>> wrote:
> 
>     Myles Watson wrote:
>      > Did you see my concern with checking the device instead of the ROM?
>      >
>      > Thanks,
>      > Myles
>     oops sorry.. I missed that one..
> 
> No problem.
>  
> 
>     Hm.. not sure.. that particular check does not seem to be a consistency
>     check but rather a check to determine from which location to run the VGA
>     OPROM from... Generally, VGA oproms should run from 0xc0000.
> 
> Yes.  His card is broken.  I just wanted to make sure the change doesn't 
> break other things to enable his 10-year-old card.
>  
> 
>     Maybe we should add another check whether class of the card and class of
>     the device are the same?
> 
> If we did, that would break his card again.
> 
> I guess someone will complain if/when it matters.  I'm not sure what the 
> "right" thing to do is.

I did think about this before I submitted my original patch, but didn't 
write my thoughts down anywhere, so here goes:

In pci_rom.c::pci_rom_brobe there is a check to see if the VID/PID of 
the device, as read from the PCI config space, matches the ROM image. 
This check was in the original code, and should be there.  I like it - 
it protects against user error.

There is also a check to see if the "class of device" as read from the 
PCI config space matches that contained in the ROM image.  This seems 
like a reasonable check to make, and to print a message if it fails, but 
I think the code should push on, even if this fails.

The change I made was a little later on, once we have decided to load 
the ROM image.  We have to do something different if the device we are 
loading the ROM for is a VGA (it has to be at 0xC000, and should be done 
early).  My change was to make this check based on the PCI config space 
- not the ROM image.  My thinking was along the lines that if someone 
made a PCI card that didn't declare itself to be a VGA in the PCI config 
space then most software wouldn't treat it as a VGA device.  (in other 
words the PCI config space is more likely to be correct than the ROM).

This also more closely matches my understanding of how this code might 
be called.  There would be one call early on where the first VGA device 
has it's ROM loaded, and then there would be a second pass where the non 
VGA devices have there ROMs loaded.

The final argument for having the code like I had it was that my PCI VGA 
card was quite popular, back in the day[*], and I assume that it must 
have worked with almost every motherboard out there, so legacy BIOSs 
must have been equally lax.

MM

Patch

Index: util/x86emu/x86_interrupts.c
===================================================================
--- util/x86emu/x86_interrupts.c	(revision 4855)
+++ util/x86emu/x86_interrupts.c	(working copy)
@@ -35,13 +35,14 @@ 
 
 enum {
 	CHECK = 0xb001,
-	FINDDEV = 0xb102,
-	READCONFBYTE = 0xb108,
-	READCONFWORD = 0xb109,
-	READCONFDWORD = 0xb10a,
-	WRITECONFBYTE = 0xb10b,
-	WRITECONFWORD = 0xb10c,
-	WRITECONFDWORD = 0xb10d
+	PCIBIOS_CHECK = 0xb101,
+	PCIBIOS_FINDDEV = 0xb102,
+	PCIBIOS_READCONFBYTE = 0xb108,
+	PCIBIOS_READCONFWORD = 0xb109,
+	PCIBIOS_READCONFDWORD = 0xb10a,
+	PCIBIOS_WRITECONFBYTE = 0xb10b,
+	PCIBIOS_WRITECONFWORD = 0xb10c,
+	PCIBIOS_WRITECONFDWORD = 0xb10d
 };
 
 // errors go in AH. Just set these up so that word assigns
@@ -73,7 +74,12 @@ 
 		regs->ecx = 0x2049;
 		retval = 0;
 		break;
-	case FINDDEV:
+	case  PCIBIOS_CHECK:
+		regs->edx = 0x20494350; /* ' ICP' */
+		regs->edi = 0x00000000; /* protected mode entry */
+		retval = 0;
+		break;
+	case PCIBIOS_FINDDEV:
 	{
 		devid = regs->ecx;
 		vendorid = regs->edx;
@@ -104,12 +110,12 @@ 
 		}
 	}
 	break;
-	case READCONFDWORD:
-	case READCONFWORD:
-	case READCONFBYTE:
-	case WRITECONFDWORD:
-	case WRITECONFWORD:
-	case WRITECONFBYTE:
+	case PCIBIOS_READCONFDWORD:
+	case PCIBIOS_READCONFWORD:
+	case PCIBIOS_READCONFBYTE:
+	case PCIBIOS_WRITECONFDWORD:
+	case PCIBIOS_WRITECONFWORD:
+	case PCIBIOS_WRITECONFBYTE:
 	{
 		unsigned long dword;
 		unsigned short word;
@@ -126,39 +132,39 @@ 
 			regs->eax = PCIBIOS_BADREG;
 			retval = -1;
 		}
-		switch(func) {
-		case READCONFBYTE:
-			byte = pci_read_config8(dev, reg);
-			regs->ecx = byte;
-			break;
-		case READCONFWORD:
-			word = pci_read_config16(dev, reg);
-			regs->ecx = word;
-			break;
-		case READCONFDWORD:
-			dword = pci_read_config32(dev, reg);
-			regs->ecx = dword;
-			break;
-		case WRITECONFBYTE:
-			byte = regs->ecx;
-			pci_write_config8(dev, reg, byte);
-			break;
-		case WRITECONFWORD:
-			word = regs->ecx;
-			pci_write_config16(dev, reg, word);
-			break;
-		case WRITECONFDWORD:
-			dword = regs->ecx;
-			pci_write_config32(dev, reg, dword);
-			break;
+		else {
+		        switch(func) {
+			case PCIBIOS_READCONFBYTE:
+			        byte = pci_read_config8(dev, reg);
+				regs->ecx = byte;
+				break;
+			case PCIBIOS_READCONFWORD:
+			        word = pci_read_config16(dev, reg);
+				regs->ecx = word;
+				break;
+			case PCIBIOS_READCONFDWORD:
+			        dword = pci_read_config32(dev, reg);
+				regs->ecx = dword;
+				break;
+			case PCIBIOS_WRITECONFBYTE:
+			        byte = regs->ecx;
+				pci_write_config8(dev, reg, byte);
+				break;
+			case PCIBIOS_WRITECONFWORD:
+			        word = regs->ecx;
+				pci_write_config16(dev, reg, word);
+				break;
+			case PCIBIOS_WRITECONFDWORD:
+			        dword = regs->ecx;
+				pci_write_config32(dev, reg, dword);
+				break;
+			}
+			
+			printk(BIOS_DEBUG, "0x%x: bus %d devfn 0x%x reg 0x%x val 0x%x\n",
+			       func, bus, devfn, reg, regs->ecx);
+			regs->eax = 0;
+			retval = 0;
 		}
-
-		if (retval)
-			retval = PCIBIOS_BADREG;
-		printk(BIOS_DEBUG, "0x%x: bus %d devfn 0x%x reg 0x%x val 0x%x\n",
-			     func, bus, devfn, reg, regs->ecx);
-		regs->eax = 0;
-		retval = 0;
 	}
 	break;
 	default: