Message ID | 1345144427-7175-1-git-send-email-alexdeucher@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Thu, Aug 16, 2012 at 03:13:46PM -0400, alexdeucher@gmail.com wrote: > From: David L <equinox-freedesktopbugs@diac24.net> > > This is required for pure UEFI systems. The vbios is stored > in ACPI rather than at the legacy vga location. > > Fixes: > https://bugs.freedesktop.org/show_bug.cgi?id=26891 > > V2: fix #ifdefs as per Greg's comments > > Signed-off-by: Alex Deucher <alexander.deucher@amd.com> > Cc: stable@vger.kernel.org > --- > drivers/gpu/drm/radeon/radeon_bios.c | 62 ++++++++++++++++++++++++++++++++++ > 1 files changed, 62 insertions(+), 0 deletions(-) > > diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c > index 501f488..bf21f65 100644 > --- a/drivers/gpu/drm/radeon/radeon_bios.c > +++ b/drivers/gpu/drm/radeon/radeon_bios.c > @@ -32,6 +32,9 @@ > > #include <linux/vga_switcheroo.h> > #include <linux/slab.h> > +#ifdef CONFIG_ACPI > +#include <linux/acpi.h> > +#endif You forgot to remove this one :( > /* > * BIOS. > */ > @@ -476,6 +479,63 @@ static bool radeon_read_disabled_bios(struct radeon_device *rdev) > return legacy_read_disabled_bios(rdev); > } > > +#ifdef CONFIG_ACPI > +static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) > +{ > + bool ret = false; > + struct acpi_table_header *hdr; > + /* acpi_get_table_with_size is not exported :( */ > + acpi_size tbl_size = 0x7fffffff; > + UEFI_ACPI_VFCT *vfct; > + GOP_VBIOS_CONTENT *vbios; > + VFCT_IMAGE_HEADER *vhdr; > + > + if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr))) > + return false; > + if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { > + DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); > + goto out_unmap; > + } > + > + vfct = (UEFI_ACPI_VFCT *)hdr; > + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) { > + DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); > + goto out_unmap; > + } > + > + vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset); > + vhdr = &vbios->VbiosHeader; > + DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n", > + vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction, > + vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength); > + > + if (vhdr->PCIBus != rdev->pdev->bus->number || > + vhdr->PCIDevice != PCI_SLOT(rdev->pdev->devfn) || > + vhdr->PCIFunction != PCI_FUNC(rdev->pdev->devfn) || > + vhdr->VendorID != rdev->pdev->vendor || > + vhdr->DeviceID != rdev->pdev->device) { > + DRM_INFO("ACPI VFCT table is not for this card\n"); > + goto out_unmap; > + }; > + > + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) { > + DRM_ERROR("ACPI VFCT image truncated\n"); > + goto out_unmap; > + } > + > + rdev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL); > + ret = !!rdev->bios; > + > +out_unmap: > + /* uh, no idea what to do here... */ > + return ret; > +} > +#else > +static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) Make it inline, and then the compiler is smart enough to just delete the whole if () check you make when you call it. Third time's a charm? greg k-h
On Thu, Aug 16, 2012 at 3:25 PM, Greg KH <gregkh@linuxfoundation.org> wrote: > On Thu, Aug 16, 2012 at 03:13:46PM -0400, alexdeucher@gmail.com wrote: >> From: David L <equinox-freedesktopbugs@diac24.net> >> >> This is required for pure UEFI systems. The vbios is stored >> in ACPI rather than at the legacy vga location. >> >> Fixes: >> https://bugs.freedesktop.org/show_bug.cgi?id=26891 >> >> V2: fix #ifdefs as per Greg's comments >> >> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> >> Cc: stable@vger.kernel.org >> --- >> drivers/gpu/drm/radeon/radeon_bios.c | 62 ++++++++++++++++++++++++++++++++++ >> 1 files changed, 62 insertions(+), 0 deletions(-) >> >> diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c >> index 501f488..bf21f65 100644 >> --- a/drivers/gpu/drm/radeon/radeon_bios.c >> +++ b/drivers/gpu/drm/radeon/radeon_bios.c >> @@ -32,6 +32,9 @@ >> >> #include <linux/vga_switcheroo.h> >> #include <linux/slab.h> >> +#ifdef CONFIG_ACPI >> +#include <linux/acpi.h> >> +#endif > > You forgot to remove this one :( Argh! I squashed that into the wrong patch when I rebased my fixes. > >> /* >> * BIOS. >> */ >> @@ -476,6 +479,63 @@ static bool radeon_read_disabled_bios(struct radeon_device *rdev) >> return legacy_read_disabled_bios(rdev); >> } >> >> +#ifdef CONFIG_ACPI >> +static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) >> +{ >> + bool ret = false; >> + struct acpi_table_header *hdr; >> + /* acpi_get_table_with_size is not exported :( */ >> + acpi_size tbl_size = 0x7fffffff; >> + UEFI_ACPI_VFCT *vfct; >> + GOP_VBIOS_CONTENT *vbios; >> + VFCT_IMAGE_HEADER *vhdr; >> + >> + if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr))) >> + return false; >> + if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { >> + DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); >> + goto out_unmap; >> + } >> + >> + vfct = (UEFI_ACPI_VFCT *)hdr; >> + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) { >> + DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); >> + goto out_unmap; >> + } >> + >> + vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset); >> + vhdr = &vbios->VbiosHeader; >> + DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n", >> + vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction, >> + vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength); >> + >> + if (vhdr->PCIBus != rdev->pdev->bus->number || >> + vhdr->PCIDevice != PCI_SLOT(rdev->pdev->devfn) || >> + vhdr->PCIFunction != PCI_FUNC(rdev->pdev->devfn) || >> + vhdr->VendorID != rdev->pdev->vendor || >> + vhdr->DeviceID != rdev->pdev->device) { >> + DRM_INFO("ACPI VFCT table is not for this card\n"); >> + goto out_unmap; >> + }; >> + >> + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) { >> + DRM_ERROR("ACPI VFCT image truncated\n"); >> + goto out_unmap; >> + } >> + >> + rdev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL); >> + ret = !!rdev->bios; >> + >> +out_unmap: >> + /* uh, no idea what to do here... */ >> + return ret; >> +} >> +#else >> +static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) > > Make it inline, and then the compiler is smart enough to just delete the > whole if () check you make when you call it. > > Third time's a charm? On the way. Alex
On Thu, Aug 16, 2012 at 03:13:46PM -0400, alexdeucher@gmail.com wrote: > From: David L <equinox-freedesktopbugs@diac24.net> From: David Lamparter <equinox@diac24.net> There are still two rough edges left in here, I didn't get around to clean it up, other stuff came up -- sorry... > This is required for pure UEFI systems. The vbios is stored > in ACPI rather than at the legacy vga location. > > Fixes: > https://bugs.freedesktop.org/show_bug.cgi?id=26891 > > V2: fix #ifdefs as per Greg's comments > > Signed-off-by: Alex Deucher <alexander.deucher@amd.com> > Cc: stable@vger.kernel.org > --- [...] > + struct acpi_table_header *hdr; > + /* acpi_get_table_with_size is not exported :( */ > + acpi_size tbl_size = 0x7fffffff; I was using acpi_get_table_with_size, but that needs an export, with 0x7fffffff all the tests below are kinda useless because they always succeed. I think it'd be useful to keep the length checks in case some vendor breaks their ACPI tables, so this needs an EXPORT_SYMBOL. > + UEFI_ACPI_VFCT *vfct; > + GOP_VBIOS_CONTENT *vbios; > + VFCT_IMAGE_HEADER *vhdr; > + > + if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr))) > + return false; > + if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { > + DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); > + goto out_unmap; > + } > + > + vfct = (UEFI_ACPI_VFCT *)hdr; > + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) { > + DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); > + goto out_unmap; > + } > + > + vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset); > + vhdr = &vbios->VbiosHeader; > + DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n", > + vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction, > + vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength); > + > + if (vhdr->PCIBus != rdev->pdev->bus->number || > + vhdr->PCIDevice != PCI_SLOT(rdev->pdev->devfn) || > + vhdr->PCIFunction != PCI_FUNC(rdev->pdev->devfn) || > + vhdr->VendorID != rdev->pdev->vendor || > + vhdr->DeviceID != rdev->pdev->device) { > + DRM_INFO("ACPI VFCT table is not for this card\n"); > + goto out_unmap; > + }; > + > + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) { > + DRM_ERROR("ACPI VFCT image truncated\n"); > + goto out_unmap; > + } > + > + rdev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL); > + ret = !!rdev->bios; > + > +out_unmap: > + /* uh, no idea what to do here... */ So, er, I had no clue how to clean up the return value of acpi_get_table - does this actually need to be cleaned up? Or do you just get a pointer straight to the "real" ACPI table? > + return ret; > +} > +#else > +static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) > +{ > + return false; > +} > +#endif > > bool radeon_get_bios(struct radeon_device *rdev) > { > @@ -484,6 +544,8 @@ bool radeon_get_bios(struct radeon_device *rdev) > > r = radeon_atrm_get_bios(rdev); > if (r == false) > + r = radeon_acpi_vfct_bios(rdev); > + if (r == false) > r = igp_read_bios_from_vram(rdev); > if (r == false) > r = radeon_read_bios(rdev); > -- > 1.7.7.5 > Cheers, -David
On Thu, Aug 16, 2012 at 3:40 PM, David Lamparter <equinox@diac24.net> wrote: > On Thu, Aug 16, 2012 at 03:13:46PM -0400, alexdeucher@gmail.com wrote: >> From: David L <equinox-freedesktopbugs@diac24.net> > From: David Lamparter <equinox@diac24.net> > > There are still two rough edges left in here, I didn't get around to > clean it up, other stuff came up -- sorry... > >> This is required for pure UEFI systems. The vbios is stored >> in ACPI rather than at the legacy vga location. >> >> Fixes: >> https://bugs.freedesktop.org/show_bug.cgi?id=26891 >> >> V2: fix #ifdefs as per Greg's comments >> >> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> >> Cc: stable@vger.kernel.org >> --- > [...] >> + struct acpi_table_header *hdr; >> + /* acpi_get_table_with_size is not exported :( */ >> + acpi_size tbl_size = 0x7fffffff; > > I was using acpi_get_table_with_size, but that needs an export, with > 0x7fffffff all the tests below are kinda useless because they always > succeed. I think it'd be useful to keep the length checks in case some > vendor breaks their ACPI tables, so this needs an EXPORT_SYMBOL. I guess we could leave it as is for now for -fixes and then switch it use use the new exported symbol for -next? Is it ok to export a new symbol for -fixes? > >> + UEFI_ACPI_VFCT *vfct; >> + GOP_VBIOS_CONTENT *vbios; >> + VFCT_IMAGE_HEADER *vhdr; >> + >> + if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr))) >> + return false; >> + if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { >> + DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); >> + goto out_unmap; >> + } >> + >> + vfct = (UEFI_ACPI_VFCT *)hdr; >> + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) { >> + DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); >> + goto out_unmap; >> + } >> + >> + vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset); >> + vhdr = &vbios->VbiosHeader; >> + DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n", >> + vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction, >> + vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength); >> + >> + if (vhdr->PCIBus != rdev->pdev->bus->number || >> + vhdr->PCIDevice != PCI_SLOT(rdev->pdev->devfn) || >> + vhdr->PCIFunction != PCI_FUNC(rdev->pdev->devfn) || >> + vhdr->VendorID != rdev->pdev->vendor || >> + vhdr->DeviceID != rdev->pdev->device) { >> + DRM_INFO("ACPI VFCT table is not for this card\n"); >> + goto out_unmap; >> + }; >> + >> + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) { >> + DRM_ERROR("ACPI VFCT image truncated\n"); >> + goto out_unmap; >> + } >> + >> + rdev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL); >> + ret = !!rdev->bios; >> + >> +out_unmap: >> + /* uh, no idea what to do here... */ > > So, er, I had no clue how to clean up the return value of acpi_get_table > - does this actually need to be cleaned up? Or do you just get a > pointer straight to the "real" ACPI table? Not sure on that. Anyone know more about the acpi code? Alex
Adding Matthew in case he as any ideas. On Thu, Aug 16, 2012 at 3:51 PM, Alex Deucher <alexdeucher@gmail.com> wrote: > On Thu, Aug 16, 2012 at 3:40 PM, David Lamparter <equinox@diac24.net> wrote: >> On Thu, Aug 16, 2012 at 03:13:46PM -0400, alexdeucher@gmail.com wrote: >>> From: David L <equinox-freedesktopbugs@diac24.net> >> From: David Lamparter <equinox@diac24.net> >> >> There are still two rough edges left in here, I didn't get around to >> clean it up, other stuff came up -- sorry... >> >>> This is required for pure UEFI systems. The vbios is stored >>> in ACPI rather than at the legacy vga location. >>> >>> Fixes: >>> https://bugs.freedesktop.org/show_bug.cgi?id=26891 >>> >>> V2: fix #ifdefs as per Greg's comments >>> >>> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> >>> Cc: stable@vger.kernel.org >>> --- >> [...] >>> + struct acpi_table_header *hdr; >>> + /* acpi_get_table_with_size is not exported :( */ >>> + acpi_size tbl_size = 0x7fffffff; >> >> I was using acpi_get_table_with_size, but that needs an export, with >> 0x7fffffff all the tests below are kinda useless because they always >> succeed. I think it'd be useful to keep the length checks in case some >> vendor breaks their ACPI tables, so this needs an EXPORT_SYMBOL. > > I guess we could leave it as is for now for -fixes and then switch it > use use the new exported symbol for -next? Is it ok to export a new > symbol for -fixes? > >> >>> + UEFI_ACPI_VFCT *vfct; >>> + GOP_VBIOS_CONTENT *vbios; >>> + VFCT_IMAGE_HEADER *vhdr; >>> + >>> + if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr))) >>> + return false; >>> + if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { >>> + DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); >>> + goto out_unmap; >>> + } >>> + >>> + vfct = (UEFI_ACPI_VFCT *)hdr; >>> + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) { >>> + DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); >>> + goto out_unmap; >>> + } >>> + >>> + vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset); >>> + vhdr = &vbios->VbiosHeader; >>> + DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n", >>> + vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction, >>> + vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength); >>> + >>> + if (vhdr->PCIBus != rdev->pdev->bus->number || >>> + vhdr->PCIDevice != PCI_SLOT(rdev->pdev->devfn) || >>> + vhdr->PCIFunction != PCI_FUNC(rdev->pdev->devfn) || >>> + vhdr->VendorID != rdev->pdev->vendor || >>> + vhdr->DeviceID != rdev->pdev->device) { >>> + DRM_INFO("ACPI VFCT table is not for this card\n"); >>> + goto out_unmap; >>> + }; >>> + >>> + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) { >>> + DRM_ERROR("ACPI VFCT image truncated\n"); >>> + goto out_unmap; >>> + } >>> + >>> + rdev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL); >>> + ret = !!rdev->bios; >>> + >>> +out_unmap: >>> + /* uh, no idea what to do here... */ >> >> So, er, I had no clue how to clean up the return value of acpi_get_table >> - does this actually need to be cleaned up? Or do you just get a >> pointer straight to the "real" ACPI table? > > Not sure on that. Anyone know more about the acpi code? > > Alex
On Fri, Aug 17, 2012 at 12:56:31PM -0400, Alex Deucher wrote: > > I guess we could leave it as is for now for -fixes and then switch it > > use use the new exported symbol for -next? Is it ok to export a new > > symbol for -fixes? I don't see why not, providing the ACPI people are happy with it. > >> So, er, I had no clue how to clean up the return value of acpi_get_table > >> - does this actually need to be cleaned up? Or do you just get a > >> pointer straight to the "real" ACPI table? > > > > Not sure on that. Anyone know more about the acpi code? Not sure what you're asking here - acpi_get_table returns acpi_status, not a pointer.
diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c index 501f488..bf21f65 100644 --- a/drivers/gpu/drm/radeon/radeon_bios.c +++ b/drivers/gpu/drm/radeon/radeon_bios.c @@ -32,6 +32,9 @@ #include <linux/vga_switcheroo.h> #include <linux/slab.h> +#ifdef CONFIG_ACPI +#include <linux/acpi.h> +#endif /* * BIOS. */ @@ -476,6 +479,63 @@ static bool radeon_read_disabled_bios(struct radeon_device *rdev) return legacy_read_disabled_bios(rdev); } +#ifdef CONFIG_ACPI +static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) +{ + bool ret = false; + struct acpi_table_header *hdr; + /* acpi_get_table_with_size is not exported :( */ + acpi_size tbl_size = 0x7fffffff; + UEFI_ACPI_VFCT *vfct; + GOP_VBIOS_CONTENT *vbios; + VFCT_IMAGE_HEADER *vhdr; + + if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr))) + return false; + if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { + DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); + goto out_unmap; + } + + vfct = (UEFI_ACPI_VFCT *)hdr; + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) { + DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); + goto out_unmap; + } + + vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset); + vhdr = &vbios->VbiosHeader; + DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n", + vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction, + vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength); + + if (vhdr->PCIBus != rdev->pdev->bus->number || + vhdr->PCIDevice != PCI_SLOT(rdev->pdev->devfn) || + vhdr->PCIFunction != PCI_FUNC(rdev->pdev->devfn) || + vhdr->VendorID != rdev->pdev->vendor || + vhdr->DeviceID != rdev->pdev->device) { + DRM_INFO("ACPI VFCT table is not for this card\n"); + goto out_unmap; + }; + + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) { + DRM_ERROR("ACPI VFCT image truncated\n"); + goto out_unmap; + } + + rdev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL); + ret = !!rdev->bios; + +out_unmap: + /* uh, no idea what to do here... */ + return ret; +} +#else +static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) +{ + return false; +} +#endif bool radeon_get_bios(struct radeon_device *rdev) { @@ -484,6 +544,8 @@ bool radeon_get_bios(struct radeon_device *rdev) r = radeon_atrm_get_bios(rdev); if (r == false) + r = radeon_acpi_vfct_bios(rdev); + if (r == false) r = igp_read_bios_from_vram(rdev); if (r == false) r = radeon_read_bios(rdev);