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