diff options
author | Ken Xue <Ken.Xue@amd.com> | 2016-12-21 05:35:28 -0500 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2017-01-27 11:12:45 -0500 |
commit | 919db4c199127781cef99b7ea0b74e3a9572ea32 (patch) | |
tree | f9a3b67354b1bd385d671790561ba811db6ba91c /drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | |
parent | 33503e9e5a5a0ba64ce1e5a4115ec32a6a026fe4 (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.c | 179 |
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 | */ | ||
48 | static 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 | ||
83 | bool amdgpu_read_bios(struct amdgpu_device *adev) | 130 | bool 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 | ||
146 | static bool amdgpu_read_platform_bios(struct amdgpu_device *adev) | 199 | static 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 |
299 | static bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev) | 356 | static 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 | ||
346 | out_unmap: | 408 | return true; |
347 | return ret; | ||
348 | } | 409 | } |
349 | #else | 410 | #else |
350 | static inline bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev) | 411 | static 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 | ||
356 | bool amdgpu_get_bios(struct amdgpu_device *adev) | 417 | bool 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; |
407 | free_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 | } |