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