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