diff options
author | monk.liu <Monk.Liu@amd.com> | 2015-10-29 07:33:06 (GMT) |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2015-12-02 17:45:59 (GMT) |
commit | f930b2e8628f4e6e818ea69a426a2b732679e15b (patch) | |
tree | 1ed102e53bef2c94ce514d82a6875efe2acd8a58 /drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | |
parent | 95addb2ae06f46cd13346ed87bbda3990438a69b (diff) | |
download | linux-f930b2e8628f4e6e818ea69a426a2b732679e15b.tar.xz |
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>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 58 |
1 files changed, 50 insertions, 8 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c index c44c0c6..80add22 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c @@ -35,6 +35,13 @@ * 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, * 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 @@ -58,7 +65,7 @@ static bool igp_read_bios_from_vram(struct amdgpu_device *adev) return false; } - if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) { + if (size == 0 || !AMD_IS_VALID_VBIOS(bios)) { iounmap(bios); 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) { - uint8_t __iomem *bios, val1, val2; + uint8_t __iomem *bios, val[2]; size_t size; adev->bios = NULL; @@ -84,10 +91,10 @@ bool amdgpu_read_bios(struct amdgpu_device *adev) return false; } - val1 = readb(&bios[0]); - val2 = readb(&bios[1]); + val[0] = readb(&bios[0]); + 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); return false; } @@ -101,6 +108,38 @@ bool amdgpu_read_bios(struct amdgpu_device *adev) 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) { uint8_t __iomem *bios; @@ -113,7 +152,7 @@ static bool amdgpu_read_platform_bios(struct amdgpu_device *adev) return false; } - if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) { + if (size == 0 || !AMD_IS_VALID_VBIOS(bios)) { return false; } adev->bios = kmemdup(bios, size, GFP_KERNEL); @@ -230,7 +269,7 @@ static bool amdgpu_atrm_get_bios(struct amdgpu_device *adev) break; } - if (i == 0 || adev->bios[0] != 0x55 || adev->bios[1] != 0xaa) { + if (i == 0 || !AMD_IS_VALID_VBIOS(adev->bios)) { kfree(adev->bios); return false; } @@ -320,6 +359,9 @@ bool amdgpu_get_bios(struct amdgpu_device *adev) if (r == false) r = amdgpu_read_bios(adev); if (r == false) { + r = amdgpu_read_bios_from_rom(adev); + } + if (r == false) { r = amdgpu_read_disabled_bios(adev); } if (r == false) { @@ -330,7 +372,7 @@ bool amdgpu_get_bios(struct amdgpu_device *adev) adev->bios = NULL; 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]); goto free_bios; } |