drm/amdgpu: Use new read bios from rom callback

Read the vbios directly from the rom.  In some cases,
e.g., virtualization, the rom is not available via
the BAR or other means.  Access it directly.

This is an updated version of Monks original patch which
uses family specific callbacks and unifies some of the
validation checking.

Reviewed-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Jammy Zhou <Jammy.Zhou@amd.com>
Signed-off-by: Monk Liu <Monk.Liu@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
monk.liu 2015-10-29 15:33:06 +08:00 committed by Alex Deucher
parent 95addb2ae0
commit f930b2e862

View file

@ -35,6 +35,13 @@
* BIOS. * BIOS.
*/ */
#define AMD_VBIOS_SIGNATURE " 761295520"
#define AMD_VBIOS_SIGNATURE_OFFSET 0x30
#define AMD_VBIOS_SIGNATURE_SIZE sizeof(AMD_VBIOS_SIGNATURE)
#define AMD_VBIOS_SIGNATURE_END (AMD_VBIOS_SIGNATURE_OFFSET + AMD_VBIOS_SIGNATURE_SIZE)
#define AMD_IS_VALID_VBIOS(p) ((p)[0] == 0x55 && (p)[1] == 0xAA)
#define AMD_VBIOS_LENGTH(p) ((p)[2] << 9)
/* If you boot an IGP board with a discrete card as the primary, /* If you boot an IGP board with a discrete card as the primary,
* the IGP rom is not accessible via the rom bar as the IGP rom is * the IGP rom is not accessible via the rom bar as the IGP rom is
* part of the system bios. On boot, the system bios puts a * part of the system bios. On boot, the system bios puts a
@ -58,7 +65,7 @@ static bool igp_read_bios_from_vram(struct amdgpu_device *adev)
return false; return false;
} }
if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) { if (size == 0 || !AMD_IS_VALID_VBIOS(bios)) {
iounmap(bios); iounmap(bios);
return false; return false;
} }
@ -74,7 +81,7 @@ static bool igp_read_bios_from_vram(struct amdgpu_device *adev)
bool amdgpu_read_bios(struct amdgpu_device *adev) bool amdgpu_read_bios(struct amdgpu_device *adev)
{ {
uint8_t __iomem *bios, val1, val2; uint8_t __iomem *bios, val[2];
size_t size; size_t size;
adev->bios = NULL; adev->bios = NULL;
@ -84,10 +91,10 @@ bool amdgpu_read_bios(struct amdgpu_device *adev)
return false; return false;
} }
val1 = readb(&bios[0]); val[0] = readb(&bios[0]);
val2 = readb(&bios[1]); val[1] = readb(&bios[1]);
if (size == 0 || val1 != 0x55 || val2 != 0xaa) { if (size == 0 || !AMD_IS_VALID_VBIOS(val)) {
pci_unmap_rom(adev->pdev, bios); pci_unmap_rom(adev->pdev, bios);
return false; return false;
} }
@ -101,6 +108,38 @@ bool amdgpu_read_bios(struct amdgpu_device *adev)
return true; return true;
} }
static bool amdgpu_read_bios_from_rom(struct amdgpu_device *adev)
{
u8 header[AMD_VBIOS_SIGNATURE_END+1] = {0};
int len;
if (!adev->asic_funcs->read_bios_from_rom)
return false;
/* validate VBIOS signature */
if (amdgpu_asic_read_bios_from_rom(adev, &header[0], sizeof(header)) == false)
return false;
header[AMD_VBIOS_SIGNATURE_END] = 0;
if ((!AMD_IS_VALID_VBIOS(header)) ||
0 != memcmp((char *)&header[AMD_VBIOS_SIGNATURE_OFFSET],
AMD_VBIOS_SIGNATURE,
strlen(AMD_VBIOS_SIGNATURE)))
return false;
/* valid vbios, go on */
len = AMD_VBIOS_LENGTH(header);
len = ALIGN(len, 4);
adev->bios = kmalloc(len, GFP_KERNEL);
if (!adev->bios) {
DRM_ERROR("no memory to allocate for BIOS\n");
return false;
}
/* read complete BIOS */
return amdgpu_asic_read_bios_from_rom(adev, adev->bios, len);
}
static bool amdgpu_read_platform_bios(struct amdgpu_device *adev) static bool amdgpu_read_platform_bios(struct amdgpu_device *adev)
{ {
uint8_t __iomem *bios; uint8_t __iomem *bios;
@ -113,7 +152,7 @@ static bool amdgpu_read_platform_bios(struct amdgpu_device *adev)
return false; return false;
} }
if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) { if (size == 0 || !AMD_IS_VALID_VBIOS(bios)) {
return false; return false;
} }
adev->bios = kmemdup(bios, size, GFP_KERNEL); adev->bios = kmemdup(bios, size, GFP_KERNEL);
@ -230,7 +269,7 @@ static bool amdgpu_atrm_get_bios(struct amdgpu_device *adev)
break; break;
} }
if (i == 0 || adev->bios[0] != 0x55 || adev->bios[1] != 0xaa) { if (i == 0 || !AMD_IS_VALID_VBIOS(adev->bios)) {
kfree(adev->bios); kfree(adev->bios);
return false; return false;
} }
@ -319,6 +358,9 @@ bool amdgpu_get_bios(struct amdgpu_device *adev)
r = igp_read_bios_from_vram(adev); r = igp_read_bios_from_vram(adev);
if (r == false) if (r == false)
r = amdgpu_read_bios(adev); r = amdgpu_read_bios(adev);
if (r == false) {
r = amdgpu_read_bios_from_rom(adev);
}
if (r == false) { if (r == false) {
r = amdgpu_read_disabled_bios(adev); r = amdgpu_read_disabled_bios(adev);
} }
@ -330,7 +372,7 @@ bool amdgpu_get_bios(struct amdgpu_device *adev)
adev->bios = NULL; adev->bios = NULL;
return false; return false;
} }
if (adev->bios[0] != 0x55 || adev->bios[1] != 0xaa) { if (!AMD_IS_VALID_VBIOS(adev->bios)) {
printk("BIOS signature incorrect %x %x\n", adev->bios[0], adev->bios[1]); printk("BIOS signature incorrect %x %x\n", adev->bios[0], adev->bios[1]);
goto free_bios; goto free_bios;
} }