amdgpu_bios.c revision 1.1.1.1 1 /* $NetBSD: amdgpu_bios.c,v 1.1.1.1 2018/08/27 01:34:43 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 #include <sys/cdefs.h>
31 __KERNEL_RCSID(0, "$NetBSD: amdgpu_bios.c,v 1.1.1.1 2018/08/27 01:34:43 riastradh Exp $");
32
33 #include <drm/drmP.h>
34 #include "amdgpu.h"
35 #include "atom.h"
36
37 #include <linux/slab.h>
38 #include <linux/acpi.h>
39 /*
40 * BIOS.
41 */
42
43 /* If you boot an IGP board with a discrete card as the primary,
44 * the IGP rom is not accessible via the rom bar as the IGP rom is
45 * part of the system bios. On boot, the system bios puts a
46 * copy of the igp rom at the start of vram if a discrete card is
47 * present.
48 */
49 static bool igp_read_bios_from_vram(struct amdgpu_device *adev)
50 {
51 uint8_t __iomem *bios;
52 resource_size_t vram_base;
53 resource_size_t size = 256 * 1024; /* ??? */
54
55 if (!(adev->flags & AMD_IS_APU))
56 if (!amdgpu_card_posted(adev))
57 return false;
58
59 adev->bios = NULL;
60 vram_base = pci_resource_start(adev->pdev, 0);
61 bios = ioremap(vram_base, size);
62 if (!bios) {
63 return false;
64 }
65
66 if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) {
67 iounmap(bios);
68 return false;
69 }
70 adev->bios = kmalloc(size, GFP_KERNEL);
71 if (adev->bios == NULL) {
72 iounmap(bios);
73 return false;
74 }
75 memcpy_fromio(adev->bios, bios, size);
76 iounmap(bios);
77 return true;
78 }
79
80 bool amdgpu_read_bios(struct amdgpu_device *adev)
81 {
82 uint8_t __iomem *bios, val1, val2;
83 size_t size;
84
85 adev->bios = NULL;
86 /* XXX: some cards may return 0 for rom size? ddx has a workaround */
87 bios = pci_map_rom(adev->pdev, &size);
88 if (!bios) {
89 return false;
90 }
91
92 val1 = readb(&bios[0]);
93 val2 = readb(&bios[1]);
94
95 if (size == 0 || val1 != 0x55 || val2 != 0xaa) {
96 pci_unmap_rom(adev->pdev, bios);
97 return false;
98 }
99 adev->bios = kzalloc(size, GFP_KERNEL);
100 if (adev->bios == NULL) {
101 pci_unmap_rom(adev->pdev, bios);
102 return false;
103 }
104 memcpy_fromio(adev->bios, bios, size);
105 pci_unmap_rom(adev->pdev, bios);
106 return true;
107 }
108
109 static bool amdgpu_read_platform_bios(struct amdgpu_device *adev)
110 {
111 uint8_t __iomem *bios;
112 size_t size;
113
114 adev->bios = NULL;
115
116 bios = pci_platform_rom(adev->pdev, &size);
117 if (!bios) {
118 return false;
119 }
120
121 if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) {
122 return false;
123 }
124 adev->bios = kmemdup(bios, size, GFP_KERNEL);
125 if (adev->bios == NULL) {
126 return false;
127 }
128
129 return true;
130 }
131
132 #ifdef CONFIG_ACPI
133 /* ATRM is used to get the BIOS on the discrete cards in
134 * dual-gpu systems.
135 */
136 /* retrieve the ROM in 4k blocks */
137 #define ATRM_BIOS_PAGE 4096
138 /**
139 * amdgpu_atrm_call - fetch a chunk of the vbios
140 *
141 * @atrm_handle: acpi ATRM handle
142 * @bios: vbios image pointer
143 * @offset: offset of vbios image data to fetch
144 * @len: length of vbios image data to fetch
145 *
146 * Executes ATRM to fetch a chunk of the discrete
147 * vbios image on PX systems (all asics).
148 * Returns the length of the buffer fetched.
149 */
150 static int amdgpu_atrm_call(acpi_handle atrm_handle, uint8_t *bios,
151 int offset, int len)
152 {
153 acpi_status status;
154 union acpi_object atrm_arg_elements[2], *obj;
155 struct acpi_object_list atrm_arg;
156 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};
157
158 atrm_arg.count = 2;
159 atrm_arg.pointer = &atrm_arg_elements[0];
160
161 atrm_arg_elements[0].type = ACPI_TYPE_INTEGER;
162 atrm_arg_elements[0].integer.value = offset;
163
164 atrm_arg_elements[1].type = ACPI_TYPE_INTEGER;
165 atrm_arg_elements[1].integer.value = len;
166
167 status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer);
168 if (ACPI_FAILURE(status)) {
169 printk("failed to evaluate ATRM got %s\n", acpi_format_exception(status));
170 return -ENODEV;
171 }
172
173 obj = (union acpi_object *)buffer.pointer;
174 memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length);
175 len = obj->buffer.length;
176 kfree(buffer.pointer);
177 return len;
178 }
179
180 static bool amdgpu_atrm_get_bios(struct amdgpu_device *adev)
181 {
182 int ret;
183 int size = 256 * 1024;
184 int i;
185 struct pci_dev *pdev = NULL;
186 acpi_handle dhandle, atrm_handle;
187 acpi_status status;
188 bool found = false;
189
190 /* ATRM is for the discrete card only */
191 if (adev->flags & AMD_IS_APU)
192 return false;
193
194 while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
195 dhandle = ACPI_HANDLE(&pdev->dev);
196 if (!dhandle)
197 continue;
198
199 status = acpi_get_handle(dhandle, "ATRM", &atrm_handle);
200 if (!ACPI_FAILURE(status)) {
201 found = true;
202 break;
203 }
204 }
205
206 if (!found) {
207 while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) {
208 dhandle = ACPI_HANDLE(&pdev->dev);
209 if (!dhandle)
210 continue;
211
212 status = acpi_get_handle(dhandle, "ATRM", &atrm_handle);
213 if (!ACPI_FAILURE(status)) {
214 found = true;
215 break;
216 }
217 }
218 }
219
220 if (!found)
221 return false;
222
223 adev->bios = kmalloc(size, GFP_KERNEL);
224 if (!adev->bios) {
225 DRM_ERROR("Unable to allocate bios\n");
226 return false;
227 }
228
229 for (i = 0; i < size / ATRM_BIOS_PAGE; i++) {
230 ret = amdgpu_atrm_call(atrm_handle,
231 adev->bios,
232 (i * ATRM_BIOS_PAGE),
233 ATRM_BIOS_PAGE);
234 if (ret < ATRM_BIOS_PAGE)
235 break;
236 }
237
238 if (i == 0 || adev->bios[0] != 0x55 || adev->bios[1] != 0xaa) {
239 kfree(adev->bios);
240 return false;
241 }
242 return true;
243 }
244 #else
245 static inline bool amdgpu_atrm_get_bios(struct amdgpu_device *adev)
246 {
247 return false;
248 }
249 #endif
250
251 static bool amdgpu_read_disabled_bios(struct amdgpu_device *adev)
252 {
253 if (adev->flags & AMD_IS_APU)
254 return igp_read_bios_from_vram(adev);
255 else
256 return amdgpu_asic_read_disabled_bios(adev);
257 }
258
259 #ifdef CONFIG_ACPI
260 static bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
261 {
262 bool ret = false;
263 struct acpi_table_header *hdr;
264 acpi_size tbl_size;
265 UEFI_ACPI_VFCT *vfct;
266 GOP_VBIOS_CONTENT *vbios;
267 VFCT_IMAGE_HEADER *vhdr;
268
269 if (!ACPI_SUCCESS(acpi_get_table_with_size("VFCT", 1, &hdr, &tbl_size)))
270 return false;
271 if (tbl_size < sizeof(UEFI_ACPI_VFCT)) {
272 DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n");
273 goto out_unmap;
274 }
275
276 vfct = (UEFI_ACPI_VFCT *)hdr;
277 if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) {
278 DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n");
279 goto out_unmap;
280 }
281
282 vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset);
283 vhdr = &vbios->VbiosHeader;
284 DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n",
285 vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction,
286 vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength);
287
288 if (vhdr->PCIBus != adev->pdev->bus->number ||
289 vhdr->PCIDevice != PCI_SLOT(adev->pdev->devfn) ||
290 vhdr->PCIFunction != PCI_FUNC(adev->pdev->devfn) ||
291 vhdr->VendorID != adev->pdev->vendor ||
292 vhdr->DeviceID != adev->pdev->device) {
293 DRM_INFO("ACPI VFCT table is not for this card\n");
294 goto out_unmap;
295 }
296
297 if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) {
298 DRM_ERROR("ACPI VFCT image truncated\n");
299 goto out_unmap;
300 }
301
302 adev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL);
303 ret = !!adev->bios;
304
305 out_unmap:
306 return ret;
307 }
308 #else
309 static inline bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
310 {
311 return false;
312 }
313 #endif
314
315 bool amdgpu_get_bios(struct amdgpu_device *adev)
316 {
317 bool r;
318 uint16_t tmp;
319
320 r = amdgpu_atrm_get_bios(adev);
321 if (r == false)
322 r = amdgpu_acpi_vfct_bios(adev);
323 if (r == false)
324 r = igp_read_bios_from_vram(adev);
325 if (r == false)
326 r = amdgpu_read_bios(adev);
327 if (r == false) {
328 r = amdgpu_read_disabled_bios(adev);
329 }
330 if (r == false) {
331 r = amdgpu_read_platform_bios(adev);
332 }
333 if (r == false || adev->bios == NULL) {
334 DRM_ERROR("Unable to locate a BIOS ROM\n");
335 adev->bios = NULL;
336 return false;
337 }
338 if (adev->bios[0] != 0x55 || adev->bios[1] != 0xaa) {
339 printk("BIOS signature incorrect %x %x\n", adev->bios[0], adev->bios[1]);
340 goto free_bios;
341 }
342
343 tmp = RBIOS16(0x18);
344 if (RBIOS8(tmp + 0x14) != 0x0) {
345 DRM_INFO("Not an x86 BIOS ROM, not using.\n");
346 goto free_bios;
347 }
348
349 adev->bios_header_start = RBIOS16(0x48);
350 if (!adev->bios_header_start) {
351 goto free_bios;
352 }
353 tmp = adev->bios_header_start + 4;
354 if (!memcmp(adev->bios + tmp, "ATOM", 4) ||
355 !memcmp(adev->bios + tmp, "MOTA", 4)) {
356 adev->is_atom_bios = true;
357 } else {
358 adev->is_atom_bios = false;
359 }
360
361 DRM_DEBUG("%sBIOS detected\n", adev->is_atom_bios ? "ATOM" : "COM");
362 return true;
363 free_bios:
364 kfree(adev->bios);
365 adev->bios = NULL;
366 return false;
367 }
368