|
From: Antonino D. <ad...@po...> - 2003-03-11 12:53:04
Attachments:
edid.diff
|
Hi, I was wondering how to get the EDID block, and my first thought was to implement DDC. But it is tricky to implement, so why not just get the EDID using an int 0x10 BIOS call? The EDID block can be read before the kernel goes into protected mode (just a short assembly code in arch/i386/boot/video.S) and this can be saved later on as struct edid_info during the kernel's setup routine. One catch though is that that the "empty_zero_page" is becoming too tight, so it will just use the same offset used by the EDD (BIOS Enhanced Disk Drive). So EDID reading will be disabled if EDD is enabled under the "Processor Type and Features" option. Then, we can also make EDID parsing more powerful. I've added some code in fbmon.c to parse the EDID block in more detail. It should be able to parse almost everything (except the color point). Currently, it just prints all the information it can find. However, I haven't tested if parsing the Detailed Monitor information is correct since the EDID block of the monitor I'm using is incomplete. One of the goals is to build a video data structure that also includes a database of video mode in fb_videomode format. This can be dynamically created per device using the supported VESA modes, manufacturer's mode and detailed timings mode information in the EDID block. The EDID block also contain information on GTF capability. With these types of displays, a video mode mode database may not be needed since all possible supported modelines can be calculated. The advantage of the above is that the driver can switch to different modes without relying on user input (of course, user-entered modelines are still preferred). Anyway, I need help in testing the code (especially the Detailed Information part). Just apply the attached patch, disable Enhanced Disk Driver support (under Processor Type and Features), and enable EDID support (under Graphics option). Finally, add the following line to the fbdev driver that you use (anywhere, but a good place is the init code): show_edid(get_EDID(pci_dev)) If using an x86 machine show_edid(get_EDID(NULL)) should also work. Reboot, check dmesg, and kindly post the ouput. Thanks. Tony PS: The patch is against linux-2.5.64 + fbdev.diff.gz |
|
From: James S. <jsi...@in...> - 2003-03-11 15:51:15
|
> I was wondering how to get the EDID block, and my first thought was to > implement DDC. But it is tricky to implement, so why not just get the > EDID using an int 0x10 BIOS call? DDC is tricky but the nice thing is it is very portable. We can do the BIOS call but that limits it support to intel family of processors. I still like to do the BIOS call still because it allows us quick supprot of EDID on intel platforms. > The EDID block can be read before the kernel goes into protected mode > (just a short assembly code in arch/i386/boot/video.S) and this can be > saved later on as struct edid_info during the kernel's setup routine. > > One catch though is that that the "empty_zero_page" is becoming too > tight, so it will just use the same offset used by the EDD (BIOS > Enhanced Disk Drive). So EDID reading will be disabled if EDD is > enabled under the "Processor Type and Features" option. I believe it is possible to read the block after we are in protect mode. Look at vesafb and also the aty128 driver allows you to probe the BIOS after we are in protect mode. I suggest we add a feild to struct screeninfo to store the address to the edid pointer. > One of the goals is to build a video data structure that also includes a > database of video mode in fb_videomode format. This can be dynamically > created per device using the supported VESA modes, manufacturer's mode > and detailed timings mode information in the EDID block. The EDID block > also contain information on GTF capability. With these types of > displays, a video mode mode database may not be needed since all > possible supported modelines can be calculated. > > The advantage of the above is that the driver can switch to different > modes without relying on user input (of course, user-entered modelines > are still preferred). Wow. I'm glad we both think alike. I was thinking the same thing except my hands are tied with working on the upper layer stuff. > Anyway, I need help in testing the code (especially the Detailed > Information part). Just apply the attached patch, disable Enhanced Disk > Driver support (under Processor Type and Features), and enable EDID > support (under Graphics option). Finally, add the following line to the > fbdev driver that you use (anywhere, but a good place is the init code): Diable Enhanced Disk support :-( I have a few suggestions. One we add a pointer to struct screen_info that points to the edid information. We can use phys_to_virt to translate that address into virtual memory. I can create a patch today and store it in the BK tree. |
|
From: Antonino D. <ad...@po...> - 2003-03-11 20:11:13
|
On Tue, 2003-03-11 at 23:49, James Simmons wrote: > > > I was wondering how to get the EDID block, and my first thought was to > > implement DDC. But it is tricky to implement, so why not just get the > > EDID using an int 0x10 BIOS call? > > DDC is tricky but the nice thing is it is very portable. We can do the > BIOS call but that limits it support to intel family of processors. > I still like to do the BIOS call still because it allows us quick supprot > of EDID on intel platforms. > That's true. The downside of course is that each driver/hardware has to have it's own i2c support. So this may not be very lightweight on first glance. Also, the int10 method is simple enough to implement and should theoretically support all x86 graphics card with a reasonably unbroken BIOS. If ppc can get the EDID via OpenFirmware, the x86 can get it via VBE int10. Theoretically, other archs that follow some kind of video standard will have this kind of support also. The downside of this method is it can only get the EDID block of the video controller/s initialized at boot time. > > The EDID block can be read before the kernel goes into protected mode > > (just a short assembly code in arch/i386/boot/video.S) and this can be > > saved later on as struct edid_info during the kernel's setup routine. > > > > One catch though is that that the "empty_zero_page" is becoming too > > tight, so it will just use the same offset used by the EDD (BIOS > > Enhanced Disk Drive). So EDID reading will be disabled if EDD is > > enabled under the "Processor Type and Features" option. > > I believe it is possible to read the block after we are in protect mode. > Look at vesafb and also the aty128 driver allows you to probe the BIOS > after we are in protect mode. I suggest we add a feild to struct > screeninfo to store the address to the edid pointer. > Not in this case. I believe there are very few int10 functions that have a protected mode interface counterpart. One of the reasons vesafb cannot switch modes is because of this. Also the int10 function is a request for the VBE to do DDC, and place the results to a buffer provided by the caller. It's possible, of course, that the VBE has it's own copy of the EDID block, but I don't know how to search for that. > > One of the goals is to build a video data structure that also includes a > > database of video mode in fb_videomode format. This can be dynamically > > created per device using the supported VESA modes, manufacturer's mode > > and detailed timings mode information in the EDID block. The EDID block > > also contain information on GTF capability. With these types of > > displays, a video mode mode database may not be needed since all > > possible supported modelines can be calculated. > > > > The advantage of the above is that the driver can switch to different > > modes without relying on user input (of course, user-entered modelines > > are still preferred). > > Wow. I'm glad we both think alike. I was thinking the same thing except my > hands are tied with working on the upper layer stuff. > > > Anyway, I need help in testing the code (especially the Detailed > > Information part). Just apply the attached patch, disable Enhanced Disk > > Driver support (under Processor Type and Features), and enable EDID > > support (under Graphics option). Finally, add the following line to the > > fbdev driver that you use (anywhere, but a good place is the init code): > > Diable Enhanced Disk support :-( I have a few suggestions. One we add a > pointer to struct screen_info that points to the edid information. We can > use phys_to_virt to translate that address into virtual memory. I can > create a patch today and store it in the BK tree. > You can't. The EDID block was placed in the "empty_zero_page", the same page shared by screen_info (and the EDD, apm, etc) at boottime . This page will get overwritten later on so an explicit save of the contents must be done. And because it's only a page (4086 bytes), there may not be enough room to squeeze in 128 bytes. The EDD already requires a buffer at offset 0x600, and I'm not sure how large is the block. Of course, if someone tells me where to squeeze in 128 bytes without overlapping the others, that is infinitely much better. Tony |
|
From: Antonino D. <ad...@po...> - 2003-03-11 21:36:11
|
On Tue, 2003-03-11 at 23:49, James Simmons wrote: > > Anyway, I need help in testing the code (especially the Detailed > > Information part). Just apply the attached patch, disable Enhanced Disk > > Driver support (under Processor Type and Features), and enable EDID > > support (under Graphics option). Finally, add the following line to the > > fbdev driver that you use (anywhere, but a good place is the init code): > > Diable Enhanced Disk support :-( I have a few suggestions. One we add a > pointer to struct screen_info that points to the edid information. We can > use phys_to_virt to translate that address into virtual memory. I can > create a patch today and store it in the BK tree. I think I found a chunk of around 500 bytes between INITRD and EDD, so we can squeeze in EDID in there :-) Although I'm confident on this, I'll feel better if someone who boots with initrd can test it. Tony |
|
From: Antonino D. <ad...@po...> - 2003-03-11 21:51:23
|
On Wed, 2003-03-12 at 05:33, Antonino Daplas wrote:
> I think I found a chunk of around 500 bytes between INITRD and EDD, so
> we can squeeze in EDID in there :-) Although I'm confident on this,
> I'll feel better if someone who boots with initrd can test it.
Forgot the patch :-)
Tony
diff -Naur linux-2.5.64-fbdev/arch/i386/boot/compressed/misc.c linux-2.5.64/arch/i386/boot/compressed/misc.c
--- linux-2.5.64-fbdev/arch/i386/boot/compressed/misc.c 2003-03-11 21:19:34.000000000 +0000
+++ linux-2.5.64/arch/i386/boot/compressed/misc.c 2003-03-11 21:07:24.000000000 +0000
@@ -91,7 +91,7 @@
#define ALT_MEM_K (*(unsigned long *)(real_mode + 0x1e0))
#endif
#define SCREEN_INFO (*(struct screen_info *)(real_mode+0))
-#define EDID_INFO (*(struct edid_info *)(real_mode+0x600))
+#define EDID_INFO (*(struct edid_info *)(real_mode+0x440))
extern char input_data[];
extern int input_len;
diff -Naur linux-2.5.64-fbdev/arch/i386/boot/video.S linux-2.5.64/arch/i386/boot/video.S
--- linux-2.5.64-fbdev/arch/i386/boot/video.S 2003-03-11 21:19:34.000000000 +0000
+++ linux-2.5.64/arch/i386/boot/video.S 2003-03-11 21:07:24.000000000 +0000
@@ -1888,7 +1888,6 @@
popw %ax
ret
-#if defined(CONFIG_EDID)
store_edid:
pushw %es # just save all affected
pushw %ax # affected registers
@@ -1914,21 +1913,22 @@
store_edid_magic:
movb $0x13, %al
movw $128, %cx
- movw $0x600, %di
+ movw $0x440, %di
cld
rep
stosb
ret
+#if defined(CONFIG_EDID)
read_edid:
movw $0x4f15, %ax
movw $0x01, %bx
movw $0x00, %cx
movw $0x01, %dx
- movw $0x600, %di
+ movw $0x440, %di
int $0x10
ret
#else
-store_edid:
+read_edid:
ret
#endif
diff -Naur linux-2.5.64-fbdev/arch/i386/kernel/setup.c linux-2.5.64/arch/i386/kernel/setup.c
--- linux-2.5.64-fbdev/arch/i386/kernel/setup.c 2003-03-11 21:19:34.000000000 +0000
+++ linux-2.5.64/arch/i386/kernel/setup.c 2003-03-11 21:07:24.000000000 +0000
@@ -496,23 +496,6 @@
#define copy_edd() do {} while (0)
#endif
-#if defined(CONFIG_EDID)
-/*
- * Since empty_zero_page has a limited size, we are going to use the
- * same offset as EDD. Thus, copying of the EDID block will only be
- * enabled if EDD is disabled.
- */
-static inline void copy_edid(void)
-{
- edid_info = EDID_INFO;
-}
-#else
-static inline void copy_edid(void)
-{
- memset(&edid_info, 0x13, 128);
-}
-#endif
-
/*
* Do NOT EVER look at the BIOS memory size location.
* It does not work on many machines.
@@ -880,7 +863,7 @@
ROOT_DEV = ORIG_ROOT_DEV;
drive_info = DRIVE_INFO;
screen_info = SCREEN_INFO;
- copy_edid();
+ edid_info = EDID_INFO;
apm_info.bios = APM_BIOS_INFO;
saved_videomode = VIDEO_MODE;
printk("Video mode to be used for restore is %lx\n", saved_videomode);
diff -Naur linux-2.5.64-fbdev/drivers/video/Kconfig linux-2.5.64/drivers/video/Kconfig
--- linux-2.5.64-fbdev/drivers/video/Kconfig 2003-03-11 21:19:34.000000000 +0000
+++ linux-2.5.64/drivers/video/Kconfig 2003-03-11 21:07:47.000000000 +0000
@@ -6,7 +6,7 @@
config EDID
bool "Get EDID block from VBE"
- depends on X86 && !EDD
+ depends on X86
config FB
bool "Support for frame buffer devices"
diff -Naur linux-2.5.64-fbdev/include/asm-i386/setup.h linux-2.5.64/include/asm-i386/setup.h
--- linux-2.5.64-fbdev/include/asm-i386/setup.h 2003-03-11 21:19:34.000000000 +0000
+++ linux-2.5.64/include/asm-i386/setup.h 2003-03-11 21:07:25.000000000 +0000
@@ -37,10 +37,10 @@
#define KERNEL_START (*(unsigned long *) (PARAM+0x214))
#define INITRD_START (*(unsigned long *) (PARAM+0x218))
#define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c))
+#define EDID_INFO (*(struct edid_info *) (PARAM+0x440))
+#define EDID_SIZE 128
#define EDD_NR (*(unsigned char *) (PARAM+EDDNR))
#define EDD_BUF ((struct edd_info *) (PARAM+EDDBUF))
-/* Note: EDID_INFO uses the same offset as EDD_BUF */
-#define EDID_INFO (*(struct edid_info *) (PARAM+EDDBUF))
#define COMMAND_LINE ((char *) (PARAM+2048))
#define COMMAND_LINE_SIZE 256
|
|
From: Jon S. <jon...@ya...> - 2003-03-11 22:05:40
|
If your in messing with the early boot sequence, why don't you make the kernel initialize all of the video cards in the system instead of only the primary one. Alsom is it really better to continue messing with these real mode X86 BIOS calls, or would it just be better to try and extract the info from the card vendors on how to do reset or get the DDC info? If we had the info about the cards we could just ignore the VBIOS and write this code into the protected mode FB drivers where it belongs. This problem just keeps recurring over and over on the non-X86 platforms; it's stupid having to carry around an X86 emulator just to run the VBIOS code. Personally I'd like to be able to insmod a fb driver for a secondary card. If the card needs it, it would get initialized, read the DDC data, and come up in a mode that makes sense. I have a user space program that can reset secondary cards using their VBIOS and emulating X86 real mode. It can probably be easily modified to get the DDC info and then IOCTL it into the fb driver. I'll post it if you want. ===== Jon Smirl jon...@ya... __________________________________________________ Do you Yahoo!? Yahoo! Web Hosting - establish your business online http://webhosting.yahoo.com |
|
From: Antonino D. <ad...@po...> - 2003-03-11 22:36:30
|
On Wed, 2003-03-12 at 06:05, Jon Smirl wrote: > If your in messing with the early boot sequence, why > don't you make the kernel initialize all of the video > cards in the system instead of only the primary one. Because I don't know how to :)? It basically just involves a far call no, if we know where the VBIOS code actually starts? Note that this will still be arch-specific. Separate non-primary card initialization code for each arch is still necessary. > > Alsom is it really better to continue messing with > these real mode X86 BIOS calls, or would it just be > better to try and extract the info from the card > vendors on how to do reset or get the DDC info? If we Initialization can only be done in real mode. Once the kernel is in protected mode, BIOS code cannot be run again (without extreme difficulty), so resetting is out of the question. Unfortunately, we don't have info from manufacturers, so we rely on some standards, such as VESA, to do it transparently for us. Still VESA code is mostly 16-bit. > had the info about the cards we could just ignore the > VBIOS and write this code into the protected mode FB > drivers where it belongs. This problem just keeps > recurring over and over on the non-X86 platforms; it's > stupid having to carry around an X86 emulator just to > run the VBIOS code. Again, most BIOS code cannot run in protected mode, so we need to emulate a real-mode environment for them. It's doubtful that Linus would want that in his kernel. Our only chance to do this is during early boot, or in user space. > > I have a user space program that can reset secondary > cards using their VBIOS and emulating X86 real mode. > It can probably be easily modified to get the DDC info > and then IOCTL it into the fb driver. I'll post it if > you want. > Yes, let me see what I can do. Tony |
|
From: Jon S. <jon...@ya...> - 2003-03-11 22:54:08
|
--- Antonino Daplas <ad...@po...> wrote: > On Wed, 2003-03-12 at 06:05, Jon Smirl wrote: > > If your in messing with the early boot sequence, > why > > don't you make the kernel initialize all of the > video > > cards in the system instead of only the primary > one. > > Because I don't know how to :)? It basically just > involves a far call > no, if we know where the VBIOS code actually starts? It is more complicated. You need to call the PCI Bios to find the video cards by their PCI class. There is already code in the kernel that calls PCIBios. arch/i386/pci/* Then you need to one by one map their ROMs (via PCI config registers) into C000:0 and call C000:3. But as you swap out the other adapters you need to disable their VGA emulation as there can only be on VGA device per system. By default the VBIOS code will enable VGA emulation on all of the adapters and they won't. You also need to record the INT vectors and make sure they get set back to the primary ones. > Note that this will still be arch-specific. > Separate non-primary card > initialization code for each arch is still > necessary. Having X86 work is better than nothing. > Again, most BIOS code cannot run in protected mode, > so we need to > emulate a real-mode environment for them. It's > doubtful that Linus > would want that in his kernel. Our only chance to > do this is during > early boot, or in user space. The right answer is to get the vendors to give us the info and then write protected mode versions of reset/DDC into the fb drivers. Until they do this everything else is a major hack. It is not possible to enter VM86 mode from a device driver. Only two choices are: early boot time or as a user app. I have to send you the app directly, it is too big for SF list. Early boot time may be a better solution. A complete implementation would reset all video adapters in the system and record their DDC info for retrieval by the FB drivers. > Tony > > ===== Jon Smirl jon...@ya... __________________________________________________ Do you Yahoo!? Yahoo! Web Hosting - establish your business online http://webhosting.yahoo.com |
|
From: Antonino D. <ad...@po...> - 2003-03-11 23:05:38
|
On Wed, 2003-03-12 at 06:54, Jon Smirl wrote: > --- Antonino Daplas <ad...@po...> wrote: > > On Wed, 2003-03-12 at 06:05, Jon Smirl wrote: > > > If your in messing with the early boot sequence, > > why > > > don't you make the kernel initialize all of the > > video > > > cards in the system instead of only the primary > > one. > > > > Because I don't know how to :)? It basically just > > involves a far call > > no, if we know where the VBIOS code actually starts? > > It is more complicated. You need to call the PCI Bios > to find the video cards by their PCI class. There is > already code in the kernel that calls PCIBios. > arch/i386/pci/* > > Then you need to one by one map their ROMs (via PCI > config registers) into C000:0 and call C000:3. But as > you swap out the other adapters you need to disable > their VGA emulation as there can only be on VGA device > per system. By default the VBIOS code will enable VGA > emulation on all of the adapters and they won't. You > also need to record the INT vectors and make sure they > get set back to the primary ones. > Yikes! No, it can't be done this way. During the early boot sequence, the kernel is not yet decompressed and loaded, so all the services the kernel provides are still unavailable. Unless you want to walk, detect, enable, etc the PCI subsystem in pure 16-bit assembly... Tony |
|
From: Jon S. <jon...@ya...> - 2003-03-11 23:42:50
|
--- Antonino Daplas <ad...@po...> wrote: > Yikes! No, it can't be done this way. During the > early boot sequence, > the kernel is not yet decompressed and loaded, so > all the services the > kernel provides are still unavailable. Unless you > want to walk, detect, > enable, etc the PCI subsystem in pure 16-bit > assembly... You don't Linux to look at the PCI subsys you make calls into the system BIOS to find the devices. > > Tony > ===== Jon Smirl jon...@ya... __________________________________________________ Do you Yahoo!? Yahoo! Web Hosting - establish your business online http://webhosting.yahoo.com |
|
From: Antonino D. <ad...@po...> - 2003-03-12 17:41:34
|
On Wed, 2003-03-12 at 07:42, Jon Smirl wrote: > --- Antonino Daplas <ad...@po...> wrote: > > Yikes! No, it can't be done this way. During the > > early boot sequence, > > the kernel is not yet decompressed and loaded, so > > all the services the > > kernel provides are still unavailable. Unless you > > want to walk, detect, > > enable, etc the PCI subsystem in pure 16-bit > > assembly... > > You don't Linux to look at the PCI subsys you make > calls into the system BIOS to find the devices. That's not the only reason. The problem is in 16-bit mode, the code can only access an address range up to only 1MB. PCI resources are located above 16MB. So in order to copy the ROM, it might be necessary to switch to 32-bit mode, copy the ROM, switch back to 16-bit mode, etc. Unless I missed some imported BIOS calls or other methods to do this or something similar in real-mode... Tony |
|
From: Jon S. <jon...@ya...> - 2003-03-12 18:16:59
|
--- Antonino Daplas <ad...@po...> wrote: > Unless I missed some imported BIOS calls or other > methods to do this or > something similar in real-mode... You missed something. The address of the VBIOS ROM can be controlled by writing to the PCI config space. You can make the ROM appear anywhere you want it to. This happens even for the boot video device. Somewhere very early in the boot the system BIOS enabled the VBIOS ROM and copied it to C000. This is the "shadow BIOS" option. ===== Jon Smirl jon...@ya... __________________________________________________ Do you Yahoo!? Yahoo! Web Hosting - establish your business online http://webhosting.yahoo.com |
|
From: Antonino D. <ad...@po...> - 2003-03-12 22:41:25
|
On Thu, 2003-03-13 at 02:16, Jon Smirl wrote: > --- Antonino Daplas <ad...@po...> wrote: > > Unless I missed some imported BIOS calls or other > > methods to do this or > > something similar in real-mode... > > You missed something. The address of the VBIOS ROM can > be controlled by writing to the PCI config space. You > can make the ROM appear anywhere you want it to. > > This happens even for the boot video device. > Somewhere very early in the boot the system BIOS > enabled the VBIOS ROM and copied it to C000. This is > the "shadow BIOS" option. > So the steps needed would be: 1. scan for pci devices looking for the vga controller type 2. if 1 is found other than the primary, disable the current controller 3. write to PCI config space of secondary controller the address you want it to appear (ie C000:0000). Can I use other addresses? 4. enable the controller 5. far call c000:0003 6. disable the controller 7. repeat Besides the finer points, did I miss anything obvious? Tony |
|
From: Jon S. <jon...@ya...> - 2003-03-12 23:36:34
|
--- Antonino Daplas <ad...@po...> wrote: > 1. scan for pci devices looking for the vga > controller type BIOS provide this via INT for find-pci-device-by-class = 3 > 2. if 1 is found other than the primary, disable > the current controller Must disable VGA ports. ROM should already be disabled. The reset program I sent you had the code for doing the disable properly. You need to poke some output ports. No need to diable primary ROM it is not enabled. C000 is a copy of it. > 3. write to PCI config space of secondary > controller the address you > want it to appear (ie C000:0000). Can I use other > addresses? The ROM will need to appear in an address space hole. Look in your BIOS for where it is leaving a hole in the 1MB. Map the VBIOS into the hole and then copy it to C000. The PC has RAM mapped to C000 so you can't map the ROM there. I believe there is a standard place for this hole probably E000 or A000 but I would need to reboot to look. > 4. enable the controller > > 5. far call c000:0003 This will set up INTs to work on secondary controller. Now call INT to get EDID data and stick it somewhere FB can find it. > 6. disable the controller > > 7. repeat 8) Move the default one back and copy it's ROM back. You will also need to fix up the INT 10 vectors to point to the correct entry points for the primary ROM. The reset code did this too. > > Besides the finer points, did I miss anything > obvious? > > Tony > ===== Jon Smirl jon...@ya... __________________________________________________ Do you Yahoo!? Yahoo! Web Hosting - establish your business online http://webhosting.yahoo.com |
|
From: Jon S. <jon...@ya...> - 2003-03-12 23:47:59
|
The system BIOS may not map the ROM into the first 1MB to copy it. It probably maps it to a high address and then plays with the X86 memory management to map a segment register to it. I am having vague recollections about doing this long ago when I worked at MS. I seem to recall there is a real mode instruction that will force a register like ES to point to a high mode address. This is how an ancient EMM driver (remember the AboveBoard and Lotus 123?) was implemented on a 386 without special hardware. So you would map the ROM to a high address, map the segment register to it, copy to C000, restore segment register and jump to C000:3. ===== Jon Smirl jon...@ya... __________________________________________________ Do you Yahoo!? Yahoo! Web Hosting - establish your business online http://webhosting.yahoo.com |
|
From: Geert U. <ge...@li...> - 2003-03-13 06:52:18
|
On 13 Mar 2003, Antonino Daplas wrote:
> On Thu, 2003-03-13 at 02:16, Jon Smirl wrote:
> > --- Antonino Daplas <ad...@po...> wrote:
> > > Unless I missed some imported BIOS calls or other
> > > methods to do this or
> > > something similar in real-mode...
> >
> > You missed something. The address of the VBIOS ROM can
> > be controlled by writing to the PCI config space. You
> > can make the ROM appear anywhere you want it to.
> >
> > This happens even for the boot video device.
> > Somewhere very early in the boot the system BIOS
> > enabled the VBIOS ROM and copied it to C000. This is
> > the "shadow BIOS" option.
> >
>
> So the steps needed would be:
>
> 1. scan for pci devices looking for the vga controller type
>
> 2. if 1 is found other than the primary, disable the current controller
>
> 3. write to PCI config space of secondary controller the address you
> want it to appear (ie C000:0000). Can I use other addresses?
>
> 4. enable the controller
>
> 5. far call c000:0003
>
> 6. disable the controller
>
> 7. repeat
>
> Besides the finer points, did I miss anything obvious?
Write a portable x86 emulator for non-ia32 platforms. Besides, you may even
want to use it on ia32 to make it less dependent on BIOS quirks (or for
machines without a PC BIOS).
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@li...
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
|
|
From: Jon S. <jon...@ya...> - 2003-03-13 15:42:05
|
--- Geert Uytterhoeven <ge...@li...> wrote: > Write a portable x86 emulator for non-ia32 > platforms. Besides, you may even > want to use it on ia32 to make it less dependent on > BIOS quirks (or for > machines without a PC BIOS). > Already have one. It's only 300K of code that needs to be ported/maintained just to call a hundred lines of code in a ROM. It also has to run in user space and can't be run in a device driver. ===== Jon Smirl jon...@ya... __________________________________________________ Do you Yahoo!? Yahoo! Web Hosting - establish your business online http://webhosting.yahoo.com |
|
From: Antonino D. <ad...@po...> - 2003-03-16 23:03:50
|
On Thu, 2003-03-13 at 14:50, Geert Uytterhoeven wrote: > On 13 Mar 2003, Antonino Daplas wrote: > > On Thu, 2003-03-13 at 02:16, Jon Smirl wrote: > > > --- Antonino Daplas <ad...@po...> wrote: > > > > Unless I missed some imported BIOS calls or other > > > > methods to do this or > > > > something similar in real-mode... > > > > > > You missed something. The address of the VBIOS ROM can > > > be controlled by writing to the PCI config space. You > > > can make the ROM appear anywhere you want it to. > > > > > > This happens even for the boot video device. > > > Somewhere very early in the boot the system BIOS > > > enabled the VBIOS ROM and copied it to C000. This is > > > the "shadow BIOS" option. > > > > > > > So the steps needed would be: > > > > 1. scan for pci devices looking for the vga controller type > > > > 2. if 1 is found other than the primary, disable the current controller > > > > 3. write to PCI config space of secondary controller the address you > > want it to appear (ie C000:0000). Can I use other addresses? I checked the PCI 2.2 specs, and it doesn't have this capability. It will give you the address of the expansion ROM, but you still have to manually copy the ROM and place it in any of the expansion areas. Unfortunately for VGA controllers, it's always C000:0000. There's a big problem in real mode: 1. COOO:0000 will be write protected by the BIOS upon initialization of the first VGA controller. This will prevent copying of the succeeding ROMS into that segment (unless you have a BIOS that supports read-write shadow ROM's). 2. Real mode does not support paging (ie copy on write tricks will not work) > > > > 4. enable the controller > > > > 5. far call c000:0003 > > > > 6. disable the controller > > > > 7. repeat > > > > Besides the finer points, did I miss anything obvious? > > Write a portable x86 emulator for non-ia32 platforms. Besides, you may even > want to use it on ia32 to make it less dependent on BIOS quirks (or for > machines without a PC BIOS). > I read Kendall's thread, and it seems a userspace vm86/vm86emu daemon might do the job. Tony |
|
From: Jon S. <jon...@ya...> - 2003-03-17 04:00:51
|
--- Antonino Daplas <ad...@po...> wrote: > > > 3. write to PCI config space of secondary > controller the address you > > > want it to appear (ie C000:0000). Can I use > other addresses? > > I checked the PCI 2.2 specs, and it doesn't have > this capability. It > will give you the address of the expansion ROM, but > you still have to > manually copy the ROM and place it in any of the > expansion areas. > Unfortunately for VGA controllers, it's always > C000:0000. You can very definitely move the ROMs to where ever you want that isn't occupied by something else. I have written code that does it. Also, the system BIOS must be moving the ROMs in order to sort things out so that they don't all appear on top of each other. You don't even need to move the ROM. Just enable it and read it's address form PCI space. The system BIOS will have sorted the addresses out so that they don't overlap. PCI config Region 6 is always the ROM see include/linux/pci.h > 1. COOO:0000 will be write protected by the BIOS > upon initialization of > the first VGA controller. This will prevent copying > of the succeeding > ROMS into that segment (unless you have a BIOS that > supports read-write > shadow ROM's). How is C000 write protected? I'm pretty sure that the ATI ROM are writing to C000. ===== Jon Smirl jon...@ya... __________________________________________________ Do you Yahoo!? Yahoo! Web Hosting - establish your business online http://webhosting.yahoo.com |
|
From: Antonino D. <ad...@po...> - 2003-03-17 07:03:39
|
On Mon, 2003-03-17 at 12:00, Jon Smirl wrote: > --- Antonino Daplas <ad...@po...> wrote: > > > > 3. write to PCI config space of secondary > > controller the address you > > > > want it to appear (ie C000:0000). Can I use > > other addresses? > > > > I checked the PCI 2.2 specs, and it doesn't have > > this capability. It > > will give you the address of the expansion ROM, but > > you still have to > > manually copy the ROM and place it in any of the > > expansion areas. > > Unfortunately for VGA controllers, it's always > > C000:0000. > > You can very definitely move the ROMs to where ever > you want that isn't occupied by something else. I have > written code that does it. Also, the system BIOS must > be moving the ROMs in order to sort things out so that > they don't all appear on top of each other. > You're talking about other device's expansion ROM's. VGA ROM's, especially for the x86, are an exception and has to be always mapped at c000:0000. > You don't even need to move the ROM. Just enable it > and read it's address form PCI space. The system BIOS > will have sorted the addresses out so that they don't > overlap. PCI config Region 6 is always the ROM see > include/linux/pci.h > > > 1. COOO:0000 will be write protected by the BIOS > > upon initialization of > > the first VGA controller. This will prevent copying > > of the succeeding > > ROMS into that segment (unless you have a BIOS that > > supports read-write > > shadow ROM's). > > How is C000 write protected? I'm pretty sure that the > ATI ROM are writing to C000. It is. C000 is write enabled by the BIOS before init. Then it calls the INIT procedure, which adjusts the initialization size before returning. Afterwards, the BIOS write-protects the block equivalent to the initialization size. Suceeding ROM's will then be mapped after this block. Remember, ROM's are supposed to be read-only, so even if they are shadowed, the BIOS write protects it. Tony |
|
From: Jon S. <jon...@ya...> - 2003-03-17 19:33:39
|
--- Antonino Daplas <ad...@po...> wrote:
> You're talking about other device's expansion ROM's.
> VGA ROM's,
> especially for the x86, are an exception and has to
> be always mapped at
> c000:0000.
Reboot and add pci=rom (case sensitive) to your kernel
parameters. That will show you where the video ROMs
are really located.
My x86 PC's boot video ROM is located at dd000000 not
C00000. C00000 is only a copy of the ROM in RAM.
01:00.0 VGA compatible controller: ATI Technologies
Inc Radeon R250 If [Radeon 9
000] (rev 01) (prog-if 00 [VGA])
Subsystem: C.P. Technology Co. Ltd: Unknown
device 2039
Flags: stepping, 66Mhz, medium devsel, IRQ 5
Memory at d0000000 (32-bit, prefetchable)
[disabled] [size=64M]
I/O ports at c000 [disabled] [size=256]
Memory at de000000 (32-bit, non-prefetchable)
[disabled] [size=64K]
Expansion ROM at dd000000 [size=128K]
Capabilities: [58] AGP version 2.0
Capabilities: [50] Power Management version 2
The ROM on my other video card is located here:
00:0b.0 VGA compatible controller: ATI Technologies
Inc Rage 128 PD/PRO TMDS (pr
og-if 00 [VGA])
Subsystem: ATI Technologies Inc Rage 128 AIW
Flags: bus master, stepping, medium devsel,
latency 32, IRQ 10
Memory at d8000000 (32-bit, prefetchable)
[size=64M]
I/O ports at e400 [size=256]
Memory at df000000 (32-bit, non-prefetchable)
[size=16K]
Expansion ROM at 20060000 [size=128K]
Capabilities: [5c] Power Management version 2
> Remember, ROM's are supposed to be read-only, so
> even if they are
> shadowed, the BIOS write protects it.
How is this write protection being achieved? Is it
done via manipulation of the processor descriptor
tables; if so just undo it.
=====
Jon Smirl
jon...@ya...
__________________________________________________
Do you Yahoo!?
Yahoo! Platinum - Watch CBS' NCAA March Madness, live on your desktop!
http://platinum.yahoo.com
|
|
From: Antonino D. <ad...@po...> - 2003-03-17 21:42:28
|
On Tue, 2003-03-18 at 03:33, Jon Smirl wrote: > --- Antonino Daplas <ad...@po...> wrote: > > You're talking about other device's expansion ROM's. > > VGA ROM's, > > especially for the x86, are an exception and has to > > be always mapped at > > c000:0000. > > Reboot and add pci=rom (case sensitive) to your kernel > parameters. That will show you where the video ROMs > are really located. > > My x86 PC's boot video ROM is located at dd000000 not > C00000. C00000 is only a copy of the ROM in RAM. That's not the problem. I can easily grab a copy of the ROM through extended memory copy, but it cannot just run anywhere. The VBIOS code (as with other BIOS code) must run in real mode (address below 1MB) and VBIOS can only run when at C000:0000 (C000:0000 is in real-mode segmented addressing, it is C0000 when translated to a linear address). Check the definition of DEFAULT_V_BIOS in the code you sent me. > How is this write protection being achieved? Is it > done via manipulation of the processor descriptor > tables; if so just undo it. Possibly through some BIOS specific thing. Usually the BIOS places it somewhere where it cannot be reached, even by the OS. Tony |
|
From: Jon S. <jon...@ya...> - 2003-03-17 22:02:16
|
The VBIOS should be position independent code and it will run at any 64K boundary. The PC bus spec simply says the video BIOS defaults to C000, it is not a requirement that it be located there. For example if you look at the aty128fb driver's find ROM routine your will notice that it is searching a broad address space for the ROM. I'm still not convinced that the memory at C000 is really hardware write protected, I think it is just RAM with a copy of the ROM in it. For example if I turn off BIOS shadowing my system will not boot. When debugging this I spent some time tracing into the ATI ROM and I was pretty sure that they are dependent on begin copied into RAM before begin run. Do you have a DOS floppy around? Just boot into DOS, start debug and see if you can change C000:0. If C000:0 is hardware write protected, there is nothing stopping the ROM from begin copied into 8000:0 or 9000:0 or whatever where there is guaranteed RAM. We would just need to temporarily get the kernel out of the way. ===== Jon Smirl jon...@ya... __________________________________________________ Do you Yahoo!? Yahoo! Platinum - Watch CBS' NCAA March Madness, live on your desktop! http://platinum.yahoo.com |
|
From: Antonino D. <ad...@po...> - 2003-03-17 22:33:26
|
On Tue, 2003-03-18 at 06:02, Jon Smirl wrote:
> The VBIOS should be position independent code and it
> will run at any 64K boundary. The PC bus spec simply
> says the video BIOS defaults to C000, it is not a
> requirement that it be located there. For example if
> you look at the aty128fb driver's find ROM routine
> your will notice that it is searching a broad address
> space for the ROM.
>
> I'm still not convinced that the memory at C000 is
> really hardware write protected, I think it is just
> RAM with a copy of the ROM in it. For example if I
> turn off BIOS shadowing my system will not boot. When
> debugging this I spent some time tracing into the ATI
> ROM and I was pretty sure that they are dependent on
> begin copied into RAM before begin run.
The PC-compatible specific set of steps for the system POST code
when handling each expansion ROM are:
1. Map and enable the expansion ROM to an unoccupied area of the
memory address space.
2. Find the proper image in the ROM and copy it from ROM into the
compatibility area of RAM (typically 0C0000h to 0DFFFFhh) using the
number of bytes specified by Initialization Size.
3. Disable the Expansion ROM Base Address register.
4. Leave the RAM area writable and call the INIT function.
5. Use the byte at offset 02h (which may have been modified) to
determine how much memory is used at runtime.
Before system boot, the POST code must make the RAM area containing
expansion ROM code read-only.
POST code must handle VGA devices with expansion ROMs in a special
way. The VGA device's expansion BIOS must be copied to 0C0000h.
VGA devices can be identified by examining the Class Code field in
the device's Configuration Space.
-- pg. 210 PCI Local Bus Specification Revision 2.2 December 18, 1998
>
> Do you have a DOS floppy around? Just boot into DOS,
> start debug and see if you can change C000:0.
Yes, it's unchangeable.
Tony
|
|
From: Jon S. <jon...@ya...> - 2003-03-17 23:41:44
|
The C000 must be a PCI restriction, it was not there during ISA days. Plan A: how is C000:0 protected; does the chipset hardware do it or is it done via the descriptor tables? Descriptor tables can be fixed but there is probably no general solution to chipset protection. On the other hand, we may be lucky and the PCI spec has specified a standard way for enabling write protect. Could there be a BIOS INT xx function for this? Plan B is to copy the ROM to something like 8000 or 9000. But the question there is, are VBIOS ROMs still written to run position independent give the PCI C000 requirement? Plan C is go into VM86 mode during early boot and remap the memory. Plan D would be to get enough info to write the code in protected mode. Are there more ways to do this? I'll go poke around in google and see what I can come up with. Let me know if you come up with anything. ===== Jon Smirl jon...@ya... __________________________________________________ Do you Yahoo!? Yahoo! Platinum - Watch CBS' NCAA March Madness, live on your desktop! http://platinum.yahoo.com |