diff options
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 c44c0c6afd1b..80add22375ee 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;  	} | 
