aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
diff options
context:
space:
mode:
authorKen Xue <Ken.Xue@amd.com>2016-12-21 05:35:28 -0500
committerAlex Deucher <alexander.deucher@amd.com>2017-01-27 11:12:45 -0500
commit919db4c199127781cef99b7ea0b74e3a9572ea32 (patch)
treef9a3b67354b1bd385d671790561ba811db6ba91c /drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
parent33503e9e5a5a0ba64ce1e5a4115ec32a6a026fe4 (diff)
drm/amdgpu: Refine the way to get atom bios
There are several ways to check out a ATOMBIOS. In previous codes, try a new way to fetch out vbios/rom, until current vbios/rom is started with 0x55aa, then check if this vbios is ATOMBIOS. Now, try a new way to fetch out vbios until all flags of ATOMBIOS are verified. Signed-off-by: Ken Xue <Ken.Xue@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@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.c179
1 files changed, 105 insertions, 74 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
index f573a953b4c3..2602ea12971e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
@@ -42,6 +42,51 @@
42#define AMD_IS_VALID_VBIOS(p) ((p)[0] == 0x55 && (p)[1] == 0xAA) 42#define AMD_IS_VALID_VBIOS(p) ((p)[0] == 0x55 && (p)[1] == 0xAA)
43#define AMD_VBIOS_LENGTH(p) ((p)[2] << 9) 43#define AMD_VBIOS_LENGTH(p) ((p)[2] << 9)
44 44
45/* Check if current bios is an ATOM BIOS.
46 * Return true if it is ATOM BIOS. Otherwise, return false.
47 */
48static bool check_atom_bios(uint8_t *bios, size_t size)
49{
50 uint16_t tmp, bios_header_start;
51
52 if (!bios || size < 0x49) {
53 DRM_INFO("vbios mem is null or mem size is wrong\n");
54 return false;
55 }
56
57 if (!AMD_IS_VALID_VBIOS(bios)) {
58 DRM_INFO("BIOS signature incorrect %x %x\n", bios[0], bios[1]);
59 return false;
60 }
61
62 tmp = bios[0x18] | (bios[0x19] << 8);
63 if (bios[tmp + 0x14] != 0x0) {
64 DRM_INFO("Not an x86 BIOS ROM\n");
65 return false;
66 }
67
68 bios_header_start = bios[0x48] | (bios[0x49] << 8);
69 if (!bios_header_start) {
70 DRM_INFO("Can't locate bios header\n");
71 return false;
72 }
73
74 tmp = bios_header_start + 4;
75 if (size < tmp) {
76 DRM_INFO("BIOS header is broken\n");
77 return false;
78 }
79
80 if (!memcmp(bios + tmp, "ATOM", 4) ||
81 !memcmp(bios + tmp, "MOTA", 4)) {
82 DRM_DEBUG("ATOMBIOS detected\n");
83 return true;
84 }
85
86 return false;
87}
88
89
45/* If you boot an IGP board with a discrete card as the primary, 90/* If you boot an IGP board with a discrete card as the primary,
46 * the IGP rom is not accessible via the rom bar as the IGP rom is 91 * the IGP rom is not accessible via the rom bar as the IGP rom is
47 * part of the system bios. On boot, the system bios puts a 92 * part of the system bios. On boot, the system bios puts a
@@ -65,10 +110,6 @@ static bool igp_read_bios_from_vram(struct amdgpu_device *adev)
65 return false; 110 return false;
66 } 111 }
67 112
68 if (size == 0 || !AMD_IS_VALID_VBIOS(bios)) {
69 iounmap(bios);
70 return false;
71 }
72 adev->bios = kmalloc(size, GFP_KERNEL); 113 adev->bios = kmalloc(size, GFP_KERNEL);
73 if (!adev->bios) { 114 if (!adev->bios) {
74 iounmap(bios); 115 iounmap(bios);
@@ -77,12 +118,18 @@ static bool igp_read_bios_from_vram(struct amdgpu_device *adev)
77 adev->bios_size = size; 118 adev->bios_size = size;
78 memcpy_fromio(adev->bios, bios, size); 119 memcpy_fromio(adev->bios, bios, size);
79 iounmap(bios); 120 iounmap(bios);
121
122 if (!check_atom_bios(adev->bios, size)) {
123 kfree(adev->bios);
124 return false;
125 }
126
80 return true; 127 return true;
81} 128}
82 129
83bool amdgpu_read_bios(struct amdgpu_device *adev) 130bool amdgpu_read_bios(struct amdgpu_device *adev)
84{ 131{
85 uint8_t __iomem *bios, val[2]; 132 uint8_t __iomem *bios;
86 size_t size; 133 size_t size;
87 134
88 adev->bios = NULL; 135 adev->bios = NULL;
@@ -92,13 +139,6 @@ bool amdgpu_read_bios(struct amdgpu_device *adev)
92 return false; 139 return false;
93 } 140 }
94 141
95 val[0] = readb(&bios[0]);
96 val[1] = readb(&bios[1]);
97
98 if (size == 0 || !AMD_IS_VALID_VBIOS(val)) {
99 pci_unmap_rom(adev->pdev, bios);
100 return false;
101 }
102 adev->bios = kzalloc(size, GFP_KERNEL); 142 adev->bios = kzalloc(size, GFP_KERNEL);
103 if (adev->bios == NULL) { 143 if (adev->bios == NULL) {
104 pci_unmap_rom(adev->pdev, bios); 144 pci_unmap_rom(adev->pdev, bios);
@@ -107,6 +147,12 @@ bool amdgpu_read_bios(struct amdgpu_device *adev)
107 adev->bios_size = size; 147 adev->bios_size = size;
108 memcpy_fromio(adev->bios, bios, size); 148 memcpy_fromio(adev->bios, bios, size);
109 pci_unmap_rom(adev->pdev, bios); 149 pci_unmap_rom(adev->pdev, bios);
150
151 if (!check_atom_bios(adev->bios, size)) {
152 kfree(adev->bios);
153 return false;
154 }
155
110 return true; 156 return true;
111} 157}
112 158
@@ -140,7 +186,14 @@ static bool amdgpu_read_bios_from_rom(struct amdgpu_device *adev)
140 adev->bios_size = len; 186 adev->bios_size = len;
141 187
142 /* read complete BIOS */ 188 /* read complete BIOS */
143 return amdgpu_asic_read_bios_from_rom(adev, adev->bios, len); 189 amdgpu_asic_read_bios_from_rom(adev, adev->bios, len);
190
191 if (!check_atom_bios(adev->bios, len)) {
192 kfree(adev->bios);
193 return false;
194 }
195
196 return true;
144} 197}
145 198
146static bool amdgpu_read_platform_bios(struct amdgpu_device *adev) 199static bool amdgpu_read_platform_bios(struct amdgpu_device *adev)
@@ -155,13 +208,17 @@ static bool amdgpu_read_platform_bios(struct amdgpu_device *adev)
155 return false; 208 return false;
156 } 209 }
157 210
158 if (size == 0 || !AMD_IS_VALID_VBIOS(bios)) { 211 adev->bios = kzalloc(size, GFP_KERNEL);
212 if (adev->bios == NULL)
159 return false; 213 return false;
160 } 214
161 adev->bios = kmemdup(bios, size, GFP_KERNEL); 215 memcpy_fromio(adev->bios, bios, size);
162 if (adev->bios == NULL) { 216
217 if (!check_atom_bios(adev->bios, size)) {
218 kfree(adev->bios);
163 return false; 219 return false;
164 } 220 }
221
165 adev->bios_size = size; 222 adev->bios_size = size;
166 223
167 return true; 224 return true;
@@ -273,7 +330,7 @@ static bool amdgpu_atrm_get_bios(struct amdgpu_device *adev)
273 break; 330 break;
274 } 331 }
275 332
276 if (i == 0 || !AMD_IS_VALID_VBIOS(adev->bios)) { 333 if (!check_atom_bios(adev->bios, size)) {
277 kfree(adev->bios); 334 kfree(adev->bios);
278 return false; 335 return false;
279 } 336 }
@@ -298,7 +355,6 @@ static bool amdgpu_read_disabled_bios(struct amdgpu_device *adev)
298#ifdef CONFIG_ACPI 355#ifdef CONFIG_ACPI
299static bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev) 356static bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
300{ 357{
301 bool ret = false;
302 struct acpi_table_header *hdr; 358 struct acpi_table_header *hdr;
303 acpi_size tbl_size; 359 acpi_size tbl_size;
304 UEFI_ACPI_VFCT *vfct; 360 UEFI_ACPI_VFCT *vfct;
@@ -310,13 +366,13 @@ static bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
310 tbl_size = hdr->length; 366 tbl_size = hdr->length;
311 if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { 367 if (tbl_size < sizeof(UEFI_ACPI_VFCT)) {
312 DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); 368 DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n");
313 goto out_unmap; 369 return false;
314 } 370 }
315 371
316 vfct = (UEFI_ACPI_VFCT *)hdr; 372 vfct = (UEFI_ACPI_VFCT *)hdr;
317 if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) { 373 if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) {
318 DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); 374 DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n");
319 goto out_unmap; 375 return false;
320 } 376 }
321 377
322 vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset); 378 vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset);
@@ -331,20 +387,25 @@ static bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
331 vhdr->VendorID != adev->pdev->vendor || 387 vhdr->VendorID != adev->pdev->vendor ||
332 vhdr->DeviceID != adev->pdev->device) { 388 vhdr->DeviceID != adev->pdev->device) {
333 DRM_INFO("ACPI VFCT table is not for this card\n"); 389 DRM_INFO("ACPI VFCT table is not for this card\n");
334 goto out_unmap; 390 return false;
335 } 391 }
336 392
337 if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) { 393 if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) {
338 DRM_ERROR("ACPI VFCT image truncated\n"); 394 DRM_ERROR("ACPI VFCT image truncated\n");
339 goto out_unmap; 395 return false;
340 } 396 }
341 397
342 adev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL); 398 adev->bios = kmemdup(&vbios->VbiosContent,
399 vhdr->ImageLength,
400 GFP_KERNEL);
401
402 if (!check_atom_bios(adev->bios, vhdr->ImageLength)) {
403 kfree(adev->bios);
404 return false;
405 }
343 adev->bios_size = vhdr->ImageLength; 406 adev->bios_size = vhdr->ImageLength;
344 ret = !!adev->bios;
345 407
346out_unmap: 408 return true;
347 return ret;
348} 409}
349#else 410#else
350static inline bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev) 411static inline bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
@@ -355,57 +416,27 @@ static inline bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
355 416
356bool amdgpu_get_bios(struct amdgpu_device *adev) 417bool amdgpu_get_bios(struct amdgpu_device *adev)
357{ 418{
358 bool r; 419 if (amdgpu_atrm_get_bios(adev))
359 uint16_t tmp, bios_header_start; 420 return true;
360 421
361 r = amdgpu_atrm_get_bios(adev); 422 if (amdgpu_acpi_vfct_bios(adev))
362 if (!r) 423 return true;
363 r = amdgpu_acpi_vfct_bios(adev);
364 if (!r)
365 r = igp_read_bios_from_vram(adev);
366 if (!r)
367 r = amdgpu_read_bios(adev);
368 if (!r) {
369 r = amdgpu_read_bios_from_rom(adev);
370 }
371 if (!r) {
372 r = amdgpu_read_disabled_bios(adev);
373 }
374 if (!r) {
375 r = amdgpu_read_platform_bios(adev);
376 }
377 if (!r || adev->bios == NULL) {
378 DRM_ERROR("Unable to locate a BIOS ROM\n");
379 adev->bios = NULL;
380 return false;
381 }
382 if (!AMD_IS_VALID_VBIOS(adev->bios)) {
383 printk("BIOS signature incorrect %x %x\n", adev->bios[0], adev->bios[1]);
384 goto free_bios;
385 }
386 424
387 tmp = RBIOS16(0x18); 425 if (igp_read_bios_from_vram(adev))
388 if (RBIOS8(tmp + 0x14) != 0x0) { 426 return true;
389 DRM_INFO("Not an x86 BIOS ROM, not using.\n");
390 goto free_bios;
391 }
392 427
393 bios_header_start = RBIOS16(0x48); 428 if (amdgpu_read_bios(adev))
394 if (!bios_header_start) { 429 return true;
395 goto free_bios;
396 }
397 430
398 /* Must be an ATOMBIOS */ 431 if (amdgpu_read_bios_from_rom(adev))
399 tmp = bios_header_start + 4; 432 return true;
400 if (memcmp(adev->bios + tmp, "ATOM", 4) &&
401 memcmp(adev->bios + tmp, "MOTA", 4)) {
402 goto free_bios;
403 }
404 433
405 DRM_DEBUG("ATOMBIOS detected\n"); 434 if (amdgpu_read_disabled_bios(adev))
406 return true; 435 return true;
407free_bios: 436
408 kfree(adev->bios); 437 if (amdgpu_read_platform_bios(adev))
409 adev->bios = NULL; 438 return true;
439
440 DRM_ERROR("Unable to locate a BIOS ROM\n");
410 return false; 441 return false;
411} 442}