|
@@ -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;
|
|
|
}
|
|
@@ -319,6 +358,9 @@ bool amdgpu_get_bios(struct amdgpu_device *adev)
|
|
|
r = igp_read_bios_from_vram(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);
|
|
|
}
|
|
@@ -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;
|
|
|
}
|