Commit f930b2e8 authored by monk.liu's avatar monk.liu Committed by Alex Deucher

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: default avatarChristian König <christian.koenig@amd.com>
Reviewed-by: default avatarJammy Zhou <Jammy.Zhou@amd.com>
Signed-off-by: default avatarMonk Liu <Monk.Liu@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 95addb2a
...@@ -35,6 +35,13 @@ ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment