xref: /openbsd-src/sys/dev/pci/drm/amd/amdgpu/amdgpu_bios.c (revision 46035553bfdd96e63c94e32da0210227ec2e3cf1)
1 /*
2  * Copyright 2008 Advanced Micro Devices, Inc.
3  * Copyright 2008 Red Hat Inc.
4  * Copyright 2009 Jerome Glisse.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22  * OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * Authors: Dave Airlie
25  *          Alex Deucher
26  *          Jerome Glisse
27  */
28 
29 #include "amdgpu.h"
30 #include "atom.h"
31 
32 #include <linux/pci.h>
33 #include <linux/slab.h>
34 #include <linux/acpi.h>
35 
36 #if defined(__amd64__) || defined(__i386__)
37 #include <dev/isa/isareg.h>
38 #include <dev/isa/isavar.h>
39 #endif
40 
41 /*
42  * BIOS.
43  */
44 
45 #define AMD_VBIOS_SIGNATURE " 761295520"
46 #define AMD_VBIOS_SIGNATURE_OFFSET 0x30
47 #define AMD_VBIOS_SIGNATURE_SIZE sizeof(AMD_VBIOS_SIGNATURE)
48 #define AMD_VBIOS_SIGNATURE_END (AMD_VBIOS_SIGNATURE_OFFSET + AMD_VBIOS_SIGNATURE_SIZE)
49 #define AMD_IS_VALID_VBIOS(p) ((p)[0] == 0x55 && (p)[1] == 0xAA)
50 #define AMD_VBIOS_LENGTH(p) ((p)[2] << 9)
51 
52 /* Check if current bios is an ATOM BIOS.
53  * Return true if it is ATOM BIOS. Otherwise, return false.
54  */
55 static bool check_atom_bios(uint8_t *bios, size_t size)
56 {
57 	uint16_t tmp, bios_header_start;
58 
59 	if (!bios || size < 0x49) {
60 		DRM_INFO("vbios mem is null or mem size is wrong\n");
61 		return false;
62 	}
63 
64 	if (!AMD_IS_VALID_VBIOS(bios)) {
65 		DRM_INFO("BIOS signature incorrect %x %x\n", bios[0], bios[1]);
66 		return false;
67 	}
68 
69 	bios_header_start = bios[0x48] | (bios[0x49] << 8);
70 	if (!bios_header_start) {
71 		DRM_INFO("Can't locate bios header\n");
72 		return false;
73 	}
74 
75 	tmp = bios_header_start + 4;
76 	if (size < tmp) {
77 		DRM_INFO("BIOS header is broken\n");
78 		return false;
79 	}
80 
81 	if (!memcmp(bios + tmp, "ATOM", 4) ||
82 	    !memcmp(bios + tmp, "MOTA", 4)) {
83 		DRM_DEBUG("ATOMBIOS detected\n");
84 		return true;
85 	}
86 
87 	return false;
88 }
89 
90 /* If you boot an IGP board with a discrete card as the primary,
91  * the IGP rom is not accessible via the rom bar as the IGP rom is
92  * part of the system bios.  On boot, the system bios puts a
93  * copy of the igp rom at the start of vram if a discrete card is
94  * present.
95  */
96 #ifdef __linux__
97 static bool igp_read_bios_from_vram(struct amdgpu_device *adev)
98 {
99 	uint8_t __iomem *bios;
100 	resource_size_t vram_base;
101 	resource_size_t size = 256 * 1024; /* ??? */
102 
103 	if (!(adev->flags & AMD_IS_APU))
104 		if (amdgpu_device_need_post(adev))
105 			return false;
106 
107 	adev->bios = NULL;
108 	vram_base = pci_resource_start(adev->pdev, 0);
109 	bios = ioremap_wc(vram_base, size);
110 	if (!bios) {
111 		return false;
112 	}
113 
114 	adev->bios = kmalloc(size, GFP_KERNEL);
115 	if (!adev->bios) {
116 		iounmap(bios);
117 		return false;
118 	}
119 	adev->bios_size = size;
120 	memcpy_fromio(adev->bios, bios, size);
121 	iounmap(bios);
122 
123 	if (!check_atom_bios(adev->bios, size)) {
124 		kfree(adev->bios);
125 		return false;
126 	}
127 
128 	return true;
129 }
130 #else
131 static bool igp_read_bios_from_vram(struct amdgpu_device *adev)
132 {
133 	uint8_t __iomem *bios;
134 	resource_size_t size = 256 * 1024; /* ??? */
135 	bus_space_handle_t bsh;
136 	bus_space_tag_t bst = adev->memt;
137 
138 	if (!(adev->flags & AMD_IS_APU))
139 		if (amdgpu_device_need_post(adev))
140 			return false;
141 
142 	adev->bios = NULL;
143 
144 	if (bus_space_map(bst, adev->fb_aper_offset, size, BUS_SPACE_MAP_LINEAR, &bsh) != 0)
145 		return false;
146 
147 	bios = bus_space_vaddr(adev->memt, bsh);
148 	if (bios == NULL) {
149 		bus_space_unmap(bst, bsh, size);
150 		return false;
151 	}
152 
153 	adev->bios = kmalloc(size, GFP_KERNEL);
154 	if (!adev->bios) {
155 		bus_space_unmap(bst, bsh, size);
156 		return false;
157 	}
158 	adev->bios_size = size;
159 	memcpy_fromio(adev->bios, bios, size);
160 	bus_space_unmap(bst, bsh, size);
161 
162 	if (!check_atom_bios(adev->bios, size)) {
163 		kfree(adev->bios);
164 		return false;
165 	}
166 
167 	return true;
168 }
169 #endif
170 
171 #ifdef __linux__
172 bool amdgpu_read_bios(struct amdgpu_device *adev)
173 {
174 	uint8_t __iomem *bios;
175 	size_t size;
176 
177 	adev->bios = NULL;
178 	/* XXX: some cards may return 0 for rom size? ddx has a workaround */
179 	bios = pci_map_rom(adev->pdev, &size);
180 	if (!bios) {
181 		return false;
182 	}
183 
184 	adev->bios = kzalloc(size, GFP_KERNEL);
185 	if (adev->bios == NULL) {
186 		pci_unmap_rom(adev->pdev, bios);
187 		return false;
188 	}
189 	adev->bios_size = size;
190 	memcpy_fromio(adev->bios, bios, size);
191 	pci_unmap_rom(adev->pdev, bios);
192 
193 	if (!check_atom_bios(adev->bios, size)) {
194 		kfree(adev->bios);
195 		return false;
196 	}
197 
198 	return true;
199 }
200 #else
201 bool amdgpu_read_bios(struct amdgpu_device *adev)
202 {
203 	uint8_t __iomem *bios;
204 	size_t size;
205 	pcireg_t address, mask;
206 	bus_space_handle_t romh;
207 	int rc;
208 
209 	adev->bios = NULL;
210 	/* XXX: some cards may return 0 for rom size? ddx has a workaround */
211 
212 	address = pci_conf_read(adev->pc, adev->pa_tag, PCI_ROM_REG);
213 	pci_conf_write(adev->pc, adev->pa_tag, PCI_ROM_REG, ~PCI_ROM_ENABLE);
214 	mask = pci_conf_read(adev->pc, adev->pa_tag, PCI_ROM_REG);
215 	address |= PCI_ROM_ENABLE;
216 	pci_conf_write(adev->pc, adev->pa_tag, PCI_ROM_REG, address);
217 
218 	size = PCI_ROM_SIZE(mask);
219 	if (size == 0)
220 		return false;
221 	rc = bus_space_map(adev->memt, PCI_ROM_ADDR(address), size,
222 	    BUS_SPACE_MAP_LINEAR, &romh);
223 	if (rc != 0) {
224 		printf(": can't map PCI ROM (%d)\n", rc);
225 		return false;
226 	}
227 	bios = (uint8_t *)bus_space_vaddr(adev->memt, romh);
228 	if (!bios) {
229 		printf(": bus_space_vaddr failed\n");
230 		return false;
231 	}
232 
233 	adev->bios = kzalloc(size, GFP_KERNEL);
234 	if (adev->bios == NULL) {
235 		bus_space_unmap(adev->memt, romh, size);
236 		return false;
237 	}
238 	adev->bios_size = size;
239 	memcpy_fromio(adev->bios, bios, size);
240 	bus_space_unmap(adev->memt, romh, size);
241 
242 	if (!check_atom_bios(adev->bios, size)) {
243 		kfree(adev->bios);
244 		return false;
245 	}
246 
247 	return true;
248 }
249 #endif
250 
251 static bool amdgpu_read_bios_from_rom(struct amdgpu_device *adev)
252 {
253 	u8 header[AMD_VBIOS_SIGNATURE_END+1] = {0};
254 	int len;
255 
256 	if (!adev->asic_funcs->read_bios_from_rom)
257 		return false;
258 
259 	/* validate VBIOS signature */
260 	if (amdgpu_asic_read_bios_from_rom(adev, &header[0], sizeof(header)) == false)
261 		return false;
262 	header[AMD_VBIOS_SIGNATURE_END] = 0;
263 
264 	if ((!AMD_IS_VALID_VBIOS(header)) ||
265 	    0 != memcmp((char *)&header[AMD_VBIOS_SIGNATURE_OFFSET],
266 			AMD_VBIOS_SIGNATURE,
267 			strlen(AMD_VBIOS_SIGNATURE)))
268 		return false;
269 
270 	/* valid vbios, go on */
271 	len = AMD_VBIOS_LENGTH(header);
272 	len = roundup2(len, 4);
273 	adev->bios = kmalloc(len, GFP_KERNEL);
274 	if (!adev->bios) {
275 		DRM_ERROR("no memory to allocate for BIOS\n");
276 		return false;
277 	}
278 	adev->bios_size = len;
279 
280 	/* read complete BIOS */
281 	amdgpu_asic_read_bios_from_rom(adev, adev->bios, len);
282 
283 	if (!check_atom_bios(adev->bios, len)) {
284 		kfree(adev->bios);
285 		return false;
286 	}
287 
288 	return true;
289 }
290 
291 #ifdef __linux__
292 static bool amdgpu_read_platform_bios(struct amdgpu_device *adev)
293 {
294 	phys_addr_t rom = adev->pdev->rom;
295 	size_t romlen = adev->pdev->romlen;
296 	void __iomem *bios;
297 
298 	adev->bios = NULL;
299 
300 	if (!rom || romlen == 0)
301 		return false;
302 
303 	adev->bios = kzalloc(romlen, GFP_KERNEL);
304 	if (!adev->bios)
305 		return false;
306 
307 	bios = ioremap(rom, romlen);
308 	if (!bios)
309 		goto free_bios;
310 
311 	memcpy_fromio(adev->bios, bios, romlen);
312 	iounmap(bios);
313 
314 	if (!check_atom_bios(adev->bios, romlen))
315 		goto free_bios;
316 
317 	adev->bios_size = romlen;
318 
319 	return true;
320 free_bios:
321 	kfree(adev->bios);
322 	return false;
323 }
324 #else
325 static bool amdgpu_read_platform_bios(struct amdgpu_device *adev)
326 {
327 #if defined(__amd64__) || defined(__i386__)
328 	uint8_t __iomem *bios;
329 	bus_size_t size = 256 * 1024; /* ??? */
330 
331 	adev->bios = NULL;
332 
333 	bios = (u8 *)ISA_HOLE_VADDR(0xc0000);
334 
335 	adev->bios = kzalloc(size, GFP_KERNEL);
336 	if (adev->bios == NULL)
337 		return false;
338 
339 	memcpy_fromio(adev->bios, bios, size);
340 
341 	if (!check_atom_bios(adev->bios, size)) {
342 		kfree(adev->bios);
343 		return false;
344 	}
345 
346 	adev->bios_size = size;
347 
348 	return true;
349 #endif
350 	return false;
351 }
352 #endif
353 
354 #ifdef CONFIG_ACPI
355 /* ATRM is used to get the BIOS on the discrete cards in
356  * dual-gpu systems.
357  */
358 /* retrieve the ROM in 4k blocks */
359 #define ATRM_BIOS_PAGE 4096
360 /**
361  * amdgpu_atrm_call - fetch a chunk of the vbios
362  *
363  * @atrm_handle: acpi ATRM handle
364  * @bios: vbios image pointer
365  * @offset: offset of vbios image data to fetch
366  * @len: length of vbios image data to fetch
367  *
368  * Executes ATRM to fetch a chunk of the discrete
369  * vbios image on PX systems (all asics).
370  * Returns the length of the buffer fetched.
371  */
372 static int amdgpu_atrm_call(acpi_handle atrm_handle, uint8_t *bios,
373 			    int offset, int len)
374 {
375 	acpi_status status;
376 	union acpi_object atrm_arg_elements[2], *obj;
377 	struct acpi_object_list atrm_arg;
378 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};
379 
380 	atrm_arg.count = 2;
381 	atrm_arg.pointer = &atrm_arg_elements[0];
382 
383 	atrm_arg_elements[0].type = ACPI_TYPE_INTEGER;
384 	atrm_arg_elements[0].integer.value = offset;
385 
386 	atrm_arg_elements[1].type = ACPI_TYPE_INTEGER;
387 	atrm_arg_elements[1].integer.value = len;
388 
389 	status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer);
390 	if (ACPI_FAILURE(status)) {
391 		printk("failed to evaluate ATRM got %s\n", acpi_format_exception(status));
392 		return -ENODEV;
393 	}
394 
395 	obj = (union acpi_object *)buffer.pointer;
396 	memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length);
397 	len = obj->buffer.length;
398 	kfree(buffer.pointer);
399 	return len;
400 }
401 
402 static bool amdgpu_atrm_get_bios(struct amdgpu_device *adev)
403 {
404 	int ret;
405 	int size = 256 * 1024;
406 	int i;
407 	struct pci_dev *pdev = NULL;
408 	acpi_handle dhandle, atrm_handle;
409 	acpi_status status;
410 	bool found = false;
411 
412 	/* ATRM is for the discrete card only */
413 	if (adev->flags & AMD_IS_APU)
414 		return false;
415 
416 	while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
417 		dhandle = ACPI_HANDLE(&pdev->dev);
418 		if (!dhandle)
419 			continue;
420 
421 		status = acpi_get_handle(dhandle, "ATRM", &atrm_handle);
422 		if (!ACPI_FAILURE(status)) {
423 			found = true;
424 			break;
425 		}
426 	}
427 
428 	if (!found) {
429 		while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) {
430 			dhandle = ACPI_HANDLE(&pdev->dev);
431 			if (!dhandle)
432 				continue;
433 
434 			status = acpi_get_handle(dhandle, "ATRM", &atrm_handle);
435 			if (!ACPI_FAILURE(status)) {
436 				found = true;
437 				break;
438 			}
439 		}
440 	}
441 
442 	if (!found)
443 		return false;
444 
445 	adev->bios = kmalloc(size, GFP_KERNEL);
446 	if (!adev->bios) {
447 		DRM_ERROR("Unable to allocate bios\n");
448 		return false;
449 	}
450 
451 	for (i = 0; i < size / ATRM_BIOS_PAGE; i++) {
452 		ret = amdgpu_atrm_call(atrm_handle,
453 				       adev->bios,
454 				       (i * ATRM_BIOS_PAGE),
455 				       ATRM_BIOS_PAGE);
456 		if (ret < ATRM_BIOS_PAGE)
457 			break;
458 	}
459 
460 	if (!check_atom_bios(adev->bios, size)) {
461 		kfree(adev->bios);
462 		return false;
463 	}
464 	adev->bios_size = size;
465 	return true;
466 }
467 #else
468 static inline bool amdgpu_atrm_get_bios(struct amdgpu_device *adev)
469 {
470 	return false;
471 }
472 #endif
473 
474 static bool amdgpu_read_disabled_bios(struct amdgpu_device *adev)
475 {
476 	if (adev->flags & AMD_IS_APU)
477 		return igp_read_bios_from_vram(adev);
478 	else
479 		return amdgpu_asic_read_disabled_bios(adev);
480 }
481 
482 #ifdef CONFIG_ACPI
483 static bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
484 {
485 	struct acpi_table_header *hdr;
486 	acpi_size tbl_size;
487 	UEFI_ACPI_VFCT *vfct;
488 	unsigned offset;
489 
490 	if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr)))
491 		return false;
492 	tbl_size = hdr->length;
493 	if (tbl_size < sizeof(UEFI_ACPI_VFCT)) {
494 		DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n");
495 		return false;
496 	}
497 
498 	vfct = (UEFI_ACPI_VFCT *)hdr;
499 	offset = vfct->VBIOSImageOffset;
500 
501 	while (offset < tbl_size) {
502 		GOP_VBIOS_CONTENT *vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + offset);
503 		VFCT_IMAGE_HEADER *vhdr = &vbios->VbiosHeader;
504 
505 		offset += sizeof(VFCT_IMAGE_HEADER);
506 		if (offset > tbl_size) {
507 			DRM_ERROR("ACPI VFCT image header truncated\n");
508 			return false;
509 		}
510 
511 		offset += vhdr->ImageLength;
512 		if (offset > tbl_size) {
513 			DRM_ERROR("ACPI VFCT image truncated\n");
514 			return false;
515 		}
516 
517 		if (vhdr->ImageLength &&
518 		    vhdr->PCIBus == adev->pdev->bus->number &&
519 		    vhdr->PCIDevice == PCI_SLOT(adev->pdev->devfn) &&
520 		    vhdr->PCIFunction == PCI_FUNC(adev->pdev->devfn) &&
521 		    vhdr->VendorID == adev->pdev->vendor &&
522 		    vhdr->DeviceID == adev->pdev->device) {
523 			adev->bios = kmemdup(&vbios->VbiosContent,
524 					     vhdr->ImageLength,
525 					     GFP_KERNEL);
526 
527 			if (!check_atom_bios(adev->bios, vhdr->ImageLength)) {
528 				kfree(adev->bios);
529 				return false;
530 			}
531 			adev->bios_size = vhdr->ImageLength;
532 			return true;
533 		}
534 	}
535 
536 	DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n");
537 	return false;
538 }
539 #else
540 static inline bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
541 {
542 	return false;
543 }
544 #endif
545 
546 bool amdgpu_get_bios(struct amdgpu_device *adev)
547 {
548 	if (amdgpu_atrm_get_bios(adev))
549 		goto success;
550 
551 	if (amdgpu_acpi_vfct_bios(adev))
552 		goto success;
553 
554 	if (igp_read_bios_from_vram(adev))
555 		goto success;
556 
557 	if (amdgpu_read_bios(adev))
558 		goto success;
559 
560 	if (amdgpu_read_bios_from_rom(adev))
561 		goto success;
562 
563 	if (amdgpu_read_disabled_bios(adev))
564 		goto success;
565 
566 	if (amdgpu_read_platform_bios(adev))
567 		goto success;
568 
569 	DRM_ERROR("Unable to locate a BIOS ROM\n");
570 	return false;
571 
572 success:
573 	adev->is_atom_fw = (adev->asic_type >= CHIP_VEGA10) ? true : false;
574 	return true;
575 }
576