| File: | dev/pci/drm/amd/amdgpu/amdgpu_bios.c |
| Warning: | line 65, column 7 The left operand of '==' is a garbage value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 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/device.h> | ||||||||
| 33 | #include <linux/pci.h> | ||||||||
| 34 | #include <linux/slab.h> | ||||||||
| 35 | #include <linux/acpi.h> | ||||||||
| 36 | |||||||||
| 37 | #if defined(__amd64__1) || defined(__i386__) | ||||||||
| 38 | #include <dev/isa/isareg.h> | ||||||||
| 39 | #include <dev/isa/isavar.h> | ||||||||
| 40 | #endif | ||||||||
| 41 | |||||||||
| 42 | /* | ||||||||
| 43 | * BIOS. | ||||||||
| 44 | */ | ||||||||
| 45 | |||||||||
| 46 | #define AMD_VBIOS_SIGNATURE" 761295520" " 761295520" | ||||||||
| 47 | #define AMD_VBIOS_SIGNATURE_OFFSET0x30 0x30 | ||||||||
| 48 | #define AMD_VBIOS_SIGNATURE_SIZEsizeof(" 761295520") sizeof(AMD_VBIOS_SIGNATURE" 761295520") | ||||||||
| 49 | #define AMD_VBIOS_SIGNATURE_END(0x30 + sizeof(" 761295520")) (AMD_VBIOS_SIGNATURE_OFFSET0x30 + AMD_VBIOS_SIGNATURE_SIZEsizeof(" 761295520")) | ||||||||
| 50 | #define AMD_IS_VALID_VBIOS(p)((p)[0] == 0x55 && (p)[1] == 0xAA) ((p)[0] == 0x55 && (p)[1] == 0xAA) | ||||||||
| 51 | #define AMD_VBIOS_LENGTH(p)((p)[2] << 9) ((p)[2] << 9) | ||||||||
| 52 | |||||||||
| 53 | /* Check if current bios is an ATOM BIOS. | ||||||||
| 54 | * Return true if it is ATOM BIOS. Otherwise, return false. | ||||||||
| 55 | */ | ||||||||
| 56 | static bool_Bool check_atom_bios(uint8_t *bios, size_t size) | ||||||||
| 57 | { | ||||||||
| 58 | uint16_t tmp, bios_header_start; | ||||||||
| 59 | |||||||||
| 60 | if (!bios
| ||||||||
| 61 | DRM_INFO("vbios mem is null or mem size is wrong\n")printk("\0016" "[" "drm" "] " "vbios mem is null or mem size is wrong\n" ); | ||||||||
| 62 | return false0; | ||||||||
| 63 | } | ||||||||
| 64 | |||||||||
| 65 | if (!AMD_IS_VALID_VBIOS(bios)((bios)[0] == 0x55 && (bios)[1] == 0xAA)) { | ||||||||
| |||||||||
| 66 | DRM_INFO("BIOS signature incorrect %x %x\n", bios[0], bios[1])printk("\0016" "[" "drm" "] " "BIOS signature incorrect %x %x\n" , bios[0], bios[1]); | ||||||||
| 67 | return false0; | ||||||||
| 68 | } | ||||||||
| 69 | |||||||||
| 70 | bios_header_start = bios[0x48] | (bios[0x49] << 8); | ||||||||
| 71 | if (!bios_header_start) { | ||||||||
| 72 | DRM_INFO("Can't locate bios header\n")printk("\0016" "[" "drm" "] " "Can't locate bios header\n"); | ||||||||
| 73 | return false0; | ||||||||
| 74 | } | ||||||||
| 75 | |||||||||
| 76 | tmp = bios_header_start + 4; | ||||||||
| 77 | if (size < tmp) { | ||||||||
| 78 | DRM_INFO("BIOS header is broken\n")printk("\0016" "[" "drm" "] " "BIOS header is broken\n"); | ||||||||
| 79 | return false0; | ||||||||
| 80 | } | ||||||||
| 81 | |||||||||
| 82 | if (!memcmp(bios + tmp, "ATOM", 4)__builtin_memcmp((bios + tmp), ("ATOM"), (4)) || | ||||||||
| 83 | !memcmp(bios + tmp, "MOTA", 4)__builtin_memcmp((bios + tmp), ("MOTA"), (4))) { | ||||||||
| 84 | DRM_DEBUG("ATOMBIOS detected\n")___drm_dbg(((void *)0), DRM_UT_CORE, "ATOMBIOS detected\n"); | ||||||||
| 85 | return true1; | ||||||||
| 86 | } | ||||||||
| 87 | |||||||||
| 88 | return false0; | ||||||||
| 89 | } | ||||||||
| 90 | |||||||||
| 91 | /* If you boot an IGP board with a discrete card as the primary, | ||||||||
| 92 | * the IGP rom is not accessible via the rom bar as the IGP rom is | ||||||||
| 93 | * part of the system bios. On boot, the system bios puts a | ||||||||
| 94 | * copy of the igp rom at the start of vram if a discrete card is | ||||||||
| 95 | * present. | ||||||||
| 96 | */ | ||||||||
| 97 | #ifdef __linux__ | ||||||||
| 98 | static bool_Bool igp_read_bios_from_vram(struct amdgpu_device *adev) | ||||||||
| 99 | { | ||||||||
| 100 | uint8_t __iomem *bios; | ||||||||
| 101 | resource_size_t vram_base; | ||||||||
| 102 | resource_size_t size = 256 * 1024; /* ??? */ | ||||||||
| 103 | |||||||||
| 104 | if (!(adev->flags & AMD_IS_APU)) | ||||||||
| 105 | if (amdgpu_device_need_post(adev)) | ||||||||
| 106 | return false0; | ||||||||
| 107 | |||||||||
| 108 | /* FB BAR not enabled */ | ||||||||
| 109 | if (pci_resource_len(adev->pdev, 0) == 0) | ||||||||
| 110 | return false0; | ||||||||
| 111 | |||||||||
| 112 | adev->bios = NULL((void *)0); | ||||||||
| 113 | vram_base = pci_resource_start(adev->pdev, 0); | ||||||||
| 114 | bios = ioremap_wc(vram_base, size); | ||||||||
| 115 | if (!bios) { | ||||||||
| 116 | return false0; | ||||||||
| 117 | } | ||||||||
| 118 | |||||||||
| 119 | adev->bios = kmalloc(size, GFP_KERNEL(0x0001 | 0x0004)); | ||||||||
| 120 | if (!adev->bios) { | ||||||||
| 121 | iounmap(bios); | ||||||||
| 122 | return false0; | ||||||||
| 123 | } | ||||||||
| 124 | adev->bios_size = size; | ||||||||
| 125 | memcpy_fromio(adev->bios, bios, size)__builtin_memcpy((adev->bios), (bios), (size)); | ||||||||
| 126 | iounmap(bios); | ||||||||
| 127 | |||||||||
| 128 | if (!check_atom_bios(adev->bios, size)) { | ||||||||
| 129 | kfree(adev->bios); | ||||||||
| 130 | return false0; | ||||||||
| 131 | } | ||||||||
| 132 | |||||||||
| 133 | return true1; | ||||||||
| 134 | } | ||||||||
| 135 | #else | ||||||||
| 136 | static bool_Bool igp_read_bios_from_vram(struct amdgpu_device *adev) | ||||||||
| 137 | { | ||||||||
| 138 | uint8_t __iomem *bios; | ||||||||
| 139 | resource_size_t size = 256 * 1024; /* ??? */ | ||||||||
| 140 | bus_space_handle_t bsh; | ||||||||
| 141 | bus_space_tag_t bst = adev->memt; | ||||||||
| 142 | |||||||||
| 143 | if (!(adev->flags & AMD_IS_APU)) | ||||||||
| 144 | if (amdgpu_device_need_post(adev)) | ||||||||
| 145 | return false0; | ||||||||
| 146 | |||||||||
| 147 | adev->bios = NULL((void *)0); | ||||||||
| 148 | |||||||||
| 149 | if (bus_space_map(bst, adev->fb_aper_offset, size, BUS_SPACE_MAP_LINEAR0x0002, &bsh) != 0) | ||||||||
| 150 | return false0; | ||||||||
| 151 | |||||||||
| 152 | bios = bus_space_vaddr(adev->memt, bsh)((adev->memt)->vaddr((bsh))); | ||||||||
| 153 | if (bios == NULL((void *)0)) { | ||||||||
| 154 | bus_space_unmap(bst, bsh, size); | ||||||||
| 155 | return false0; | ||||||||
| 156 | } | ||||||||
| 157 | |||||||||
| 158 | adev->bios = kmalloc(size, GFP_KERNEL(0x0001 | 0x0004)); | ||||||||
| 159 | if (!adev->bios) { | ||||||||
| 160 | bus_space_unmap(bst, bsh, size); | ||||||||
| 161 | return false0; | ||||||||
| 162 | } | ||||||||
| 163 | adev->bios_size = size; | ||||||||
| 164 | memcpy_fromio(adev->bios, bios, size)__builtin_memcpy((adev->bios), (bios), (size)); | ||||||||
| 165 | bus_space_unmap(bst, bsh, size); | ||||||||
| 166 | |||||||||
| 167 | if (!check_atom_bios(adev->bios, size)) { | ||||||||
| 168 | kfree(adev->bios); | ||||||||
| 169 | return false0; | ||||||||
| 170 | } | ||||||||
| 171 | |||||||||
| 172 | return true1; | ||||||||
| 173 | } | ||||||||
| 174 | #endif | ||||||||
| 175 | |||||||||
| 176 | #ifdef __linux__ | ||||||||
| 177 | bool_Bool amdgpu_read_bios(struct amdgpu_device *adev) | ||||||||
| 178 | { | ||||||||
| 179 | uint8_t __iomem *bios; | ||||||||
| 180 | size_t size; | ||||||||
| 181 | |||||||||
| 182 | adev->bios = NULL((void *)0); | ||||||||
| 183 | /* XXX: some cards may return 0 for rom size? ddx has a workaround */ | ||||||||
| 184 | bios = pci_map_rom(adev->pdev, &size); | ||||||||
| 185 | if (!bios) { | ||||||||
| 186 | return false0; | ||||||||
| 187 | } | ||||||||
| 188 | |||||||||
| 189 | adev->bios = kzalloc(size, GFP_KERNEL(0x0001 | 0x0004)); | ||||||||
| 190 | if (adev->bios == NULL((void *)0)) { | ||||||||
| 191 | pci_unmap_rom(adev->pdev, bios); | ||||||||
| 192 | return false0; | ||||||||
| 193 | } | ||||||||
| 194 | adev->bios_size = size; | ||||||||
| 195 | memcpy_fromio(adev->bios, bios, size)__builtin_memcpy((adev->bios), (bios), (size)); | ||||||||
| 196 | pci_unmap_rom(adev->pdev, bios); | ||||||||
| 197 | |||||||||
| 198 | if (!check_atom_bios(adev->bios, size)) { | ||||||||
| 199 | kfree(adev->bios); | ||||||||
| 200 | return false0; | ||||||||
| 201 | } | ||||||||
| 202 | |||||||||
| 203 | return true1; | ||||||||
| 204 | } | ||||||||
| 205 | #else | ||||||||
| 206 | bool_Bool amdgpu_read_bios(struct amdgpu_device *adev) | ||||||||
| 207 | { | ||||||||
| 208 | size_t size; | ||||||||
| 209 | pcireg_t address, mask; | ||||||||
| 210 | bus_space_handle_t romh; | ||||||||
| 211 | int rc; | ||||||||
| 212 | |||||||||
| 213 | adev->bios = NULL((void *)0); | ||||||||
| 214 | /* XXX: some cards may return 0 for rom size? ddx has a workaround */ | ||||||||
| 215 | |||||||||
| 216 | address = pci_conf_read(adev->pc, adev->pa_tag, PCI_ROM_REG0x30); | ||||||||
| 217 | pci_conf_write(adev->pc, adev->pa_tag, PCI_ROM_REG0x30, ~PCI_ROM_ENABLE0x00000001); | ||||||||
| 218 | mask = pci_conf_read(adev->pc, adev->pa_tag, PCI_ROM_REG0x30); | ||||||||
| 219 | address |= PCI_ROM_ENABLE0x00000001; | ||||||||
| 220 | pci_conf_write(adev->pc, adev->pa_tag, PCI_ROM_REG0x30, address); | ||||||||
| 221 | |||||||||
| 222 | size = PCI_ROM_SIZE(mask)(((mask) & 0xfffff800) & -((mask) & 0xfffff800)); | ||||||||
| 223 | if (size == 0) | ||||||||
| 224 | return false0; | ||||||||
| 225 | rc = bus_space_map(adev->memt, PCI_ROM_ADDR(address)((address) & 0xfffff800), size, 0, &romh); | ||||||||
| 226 | if (rc != 0) { | ||||||||
| 227 | printf(": can't map PCI ROM (%d)\n", rc); | ||||||||
| 228 | return false0; | ||||||||
| 229 | } | ||||||||
| 230 | |||||||||
| 231 | adev->bios = kzalloc(size, GFP_KERNEL(0x0001 | 0x0004)); | ||||||||
| 232 | adev->bios_size = size; | ||||||||
| 233 | bus_space_read_region_1(adev->memt, romh, 0, adev->bios, size)((adev->memt)->read_region_1((romh), (0), (adev->bios ), (size))); | ||||||||
| 234 | bus_space_unmap(adev->memt, romh, size); | ||||||||
| 235 | |||||||||
| 236 | if (!check_atom_bios(adev->bios, size)) { | ||||||||
| 237 | kfree(adev->bios); | ||||||||
| 238 | return false0; | ||||||||
| 239 | } | ||||||||
| 240 | |||||||||
| 241 | return true1; | ||||||||
| 242 | } | ||||||||
| 243 | #endif | ||||||||
| 244 | |||||||||
| 245 | static bool_Bool amdgpu_read_bios_from_rom(struct amdgpu_device *adev) | ||||||||
| 246 | { | ||||||||
| 247 | u8 header[AMD_VBIOS_SIGNATURE_END(0x30 + sizeof(" 761295520"))+1] = {0}; | ||||||||
| 248 | int len; | ||||||||
| 249 | |||||||||
| 250 | if (!adev->asic_funcs || !adev->asic_funcs->read_bios_from_rom) | ||||||||
| 251 | return false0; | ||||||||
| 252 | |||||||||
| 253 | /* validate VBIOS signature */ | ||||||||
| 254 | if (amdgpu_asic_read_bios_from_rom(adev, &header[0], sizeof(header))(adev)->asic_funcs->read_bios_from_rom((adev), (&header [0]), (sizeof(header))) == false0) | ||||||||
| 255 | return false0; | ||||||||
| 256 | header[AMD_VBIOS_SIGNATURE_END(0x30 + sizeof(" 761295520"))] = 0; | ||||||||
| 257 | |||||||||
| 258 | if ((!AMD_IS_VALID_VBIOS(header)((header)[0] == 0x55 && (header)[1] == 0xAA)) || | ||||||||
| 259 | 0 != memcmp((char *)&header[AMD_VBIOS_SIGNATURE_OFFSET],__builtin_memcmp(((char *)&header[0x30]), (" 761295520"), (strlen(" 761295520"))) | ||||||||
| 260 | AMD_VBIOS_SIGNATURE,__builtin_memcmp(((char *)&header[0x30]), (" 761295520"), (strlen(" 761295520"))) | ||||||||
| 261 | strlen(AMD_VBIOS_SIGNATURE))__builtin_memcmp(((char *)&header[0x30]), (" 761295520"), (strlen(" 761295520")))) | ||||||||
| 262 | return false0; | ||||||||
| 263 | |||||||||
| 264 | /* valid vbios, go on */ | ||||||||
| 265 | len = AMD_VBIOS_LENGTH(header)((header)[2] << 9); | ||||||||
| 266 | len = roundup2(len, 4)(((len) + ((4) - 1)) & (~((__typeof(len))(4) - 1))); | ||||||||
| 267 | adev->bios = kmalloc(len, GFP_KERNEL(0x0001 | 0x0004)); | ||||||||
| 268 | if (!adev->bios) { | ||||||||
| 269 | DRM_ERROR("no memory to allocate for BIOS\n")__drm_err("no memory to allocate for BIOS\n"); | ||||||||
| 270 | return false0; | ||||||||
| 271 | } | ||||||||
| 272 | adev->bios_size = len; | ||||||||
| 273 | |||||||||
| 274 | /* read complete BIOS */ | ||||||||
| 275 | amdgpu_asic_read_bios_from_rom(adev, adev->bios, len)(adev)->asic_funcs->read_bios_from_rom((adev), (adev-> bios), (len)); | ||||||||
| 276 | |||||||||
| 277 | if (!check_atom_bios(adev->bios, len)) { | ||||||||
| 278 | kfree(adev->bios); | ||||||||
| 279 | return false0; | ||||||||
| 280 | } | ||||||||
| 281 | |||||||||
| 282 | return true1; | ||||||||
| 283 | } | ||||||||
| 284 | |||||||||
| 285 | #ifdef __linux__ | ||||||||
| 286 | static bool_Bool amdgpu_read_platform_bios(struct amdgpu_device *adev) | ||||||||
| 287 | { | ||||||||
| 288 | phys_addr_t rom = adev->pdev->rom; | ||||||||
| 289 | size_t romlen = adev->pdev->romlen; | ||||||||
| 290 | void __iomem *bios; | ||||||||
| 291 | |||||||||
| 292 | adev->bios = NULL((void *)0); | ||||||||
| 293 | |||||||||
| 294 | if (!rom || romlen == 0) | ||||||||
| 295 | return false0; | ||||||||
| 296 | |||||||||
| 297 | adev->bios = kzalloc(romlen, GFP_KERNEL(0x0001 | 0x0004)); | ||||||||
| 298 | if (!adev->bios) | ||||||||
| 299 | return false0; | ||||||||
| 300 | |||||||||
| 301 | bios = ioremap(rom, romlen); | ||||||||
| 302 | if (!bios) | ||||||||
| 303 | goto free_bios; | ||||||||
| 304 | |||||||||
| 305 | memcpy_fromio(adev->bios, bios, romlen)__builtin_memcpy((adev->bios), (bios), (romlen)); | ||||||||
| 306 | iounmap(bios); | ||||||||
| 307 | |||||||||
| 308 | if (!check_atom_bios(adev->bios, romlen)) | ||||||||
| 309 | goto free_bios; | ||||||||
| 310 | |||||||||
| 311 | adev->bios_size = romlen; | ||||||||
| 312 | |||||||||
| 313 | return true1; | ||||||||
| 314 | free_bios: | ||||||||
| 315 | kfree(adev->bios); | ||||||||
| 316 | return false0; | ||||||||
| 317 | } | ||||||||
| 318 | #else | ||||||||
| 319 | static bool_Bool amdgpu_read_platform_bios(struct amdgpu_device *adev) | ||||||||
| 320 | { | ||||||||
| 321 | #if defined(__amd64__1) || defined(__i386__) | ||||||||
| 322 | uint8_t __iomem *bios; | ||||||||
| 323 | bus_size_t size = 256 * 1024; /* ??? */ | ||||||||
| 324 | |||||||||
| 325 | adev->bios = NULL((void *)0); | ||||||||
| 326 | |||||||||
| 327 | bios = (u8 *)ISA_HOLE_VADDR(0xc0000)((void *) ((u_long)(0xc0000) - 0x0a0000 + atdevbase)); | ||||||||
| 328 | |||||||||
| 329 | adev->bios = kzalloc(size, GFP_KERNEL(0x0001 | 0x0004)); | ||||||||
| 330 | if (adev->bios == NULL((void *)0)) | ||||||||
| 331 | return false0; | ||||||||
| 332 | |||||||||
| 333 | memcpy_fromio(adev->bios, bios, size)__builtin_memcpy((adev->bios), (bios), (size)); | ||||||||
| 334 | |||||||||
| 335 | if (!check_atom_bios(adev->bios, size)) { | ||||||||
| 336 | kfree(adev->bios); | ||||||||
| 337 | return false0; | ||||||||
| 338 | } | ||||||||
| 339 | |||||||||
| 340 | adev->bios_size = size; | ||||||||
| 341 | |||||||||
| 342 | return true1; | ||||||||
| 343 | #endif | ||||||||
| 344 | return false0; | ||||||||
| 345 | } | ||||||||
| 346 | #endif | ||||||||
| 347 | |||||||||
| 348 | #ifdef CONFIG_ACPI1 | ||||||||
| 349 | /* ATRM is used to get the BIOS on the discrete cards in | ||||||||
| 350 | * dual-gpu systems. | ||||||||
| 351 | */ | ||||||||
| 352 | /* retrieve the ROM in 4k blocks */ | ||||||||
| 353 | #define ATRM_BIOS_PAGE4096 4096 | ||||||||
| 354 | /** | ||||||||
| 355 | * amdgpu_atrm_call - fetch a chunk of the vbios | ||||||||
| 356 | * | ||||||||
| 357 | * @atrm_handle: acpi ATRM handle | ||||||||
| 358 | * @bios: vbios image pointer | ||||||||
| 359 | * @offset: offset of vbios image data to fetch | ||||||||
| 360 | * @len: length of vbios image data to fetch | ||||||||
| 361 | * | ||||||||
| 362 | * Executes ATRM to fetch a chunk of the discrete | ||||||||
| 363 | * vbios image on PX systems (all asics). | ||||||||
| 364 | * Returns the length of the buffer fetched. | ||||||||
| 365 | */ | ||||||||
| 366 | static int amdgpu_atrm_call(acpi_handle atrm_handle, uint8_t *bios, | ||||||||
| 367 | int offset, int len) | ||||||||
| 368 | { | ||||||||
| 369 | acpi_status status; | ||||||||
| 370 | union acpi_object atrm_arg_elements[2], *obj; | ||||||||
| 371 | struct acpi_object_list atrm_arg; | ||||||||
| 372 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER(size_t)-1, NULL((void *)0)}; | ||||||||
| 373 | |||||||||
| 374 | atrm_arg.count = 2; | ||||||||
| 375 | atrm_arg.pointer = &atrm_arg_elements[0]; | ||||||||
| 376 | |||||||||
| 377 | atrm_arg_elements[0].type = ACPI_TYPE_INTEGER1; | ||||||||
| 378 | atrm_arg_elements[0].integer.value = offset; | ||||||||
| 379 | |||||||||
| 380 | atrm_arg_elements[1].type = ACPI_TYPE_INTEGER1; | ||||||||
| 381 | atrm_arg_elements[1].integer.value = len; | ||||||||
| 382 | |||||||||
| 383 | status = acpi_evaluate_object(atrm_handle, NULL((void *)0), &atrm_arg, &buffer); | ||||||||
| 384 | if (ACPI_FAILURE(status)((status) != 0)) { | ||||||||
| 385 | printk("failed to evaluate ATRM got %s\n", acpi_format_exception(status)); | ||||||||
| 386 | return -ENODEV19; | ||||||||
| 387 | } | ||||||||
| 388 | |||||||||
| 389 | obj = (union acpi_object *)buffer.pointer; | ||||||||
| 390 | memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length)__builtin_memcpy((bios+offset), (obj->buffer.pointer), (obj ->buffer.length)); | ||||||||
| 391 | len = obj->buffer.length; | ||||||||
| 392 | kfree(buffer.pointer); | ||||||||
| 393 | return len; | ||||||||
| 394 | } | ||||||||
| 395 | |||||||||
| 396 | static bool_Bool amdgpu_atrm_get_bios(struct amdgpu_device *adev) | ||||||||
| 397 | { | ||||||||
| 398 | int ret; | ||||||||
| 399 | int size = 256 * 1024; | ||||||||
| 400 | int i; | ||||||||
| 401 | struct pci_dev *pdev = NULL((void *)0); | ||||||||
| 402 | acpi_handle dhandle, atrm_handle; | ||||||||
| 403 | acpi_status status; | ||||||||
| 404 | bool_Bool found = false0; | ||||||||
| 405 | |||||||||
| 406 | /* ATRM is for the discrete card only */ | ||||||||
| 407 | if (adev->flags & AMD_IS_APU) | ||||||||
| 408 | return false0; | ||||||||
| 409 | |||||||||
| 410 | /* ATRM is for on-platform devices only */ | ||||||||
| 411 | if (dev_is_removable(&adev->pdev->dev)0) | ||||||||
| 412 | return false0; | ||||||||
| 413 | |||||||||
| 414 | #ifdef notyet | ||||||||
| 415 | while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA((0x03 << 8) | 0x00) << 8, pdev)) != NULL((void *)0)) { | ||||||||
| 416 | dhandle = ACPI_HANDLE(&pdev->dev)((&pdev->dev)->node); | ||||||||
| 417 | if (!dhandle) | ||||||||
| 418 | continue; | ||||||||
| 419 | |||||||||
| 420 | status = acpi_get_handle(dhandle, "ATRM", &atrm_handle); | ||||||||
| 421 | if (ACPI_SUCCESS(status)((status) == 0)) { | ||||||||
| 422 | found = true1; | ||||||||
| 423 | break; | ||||||||
| 424 | } | ||||||||
| 425 | } | ||||||||
| 426 | |||||||||
| 427 | if (!found) { | ||||||||
| 428 | while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER((0x03 << 8) | 0x80) << 8, pdev)) != NULL((void *)0)) { | ||||||||
| 429 | dhandle = ACPI_HANDLE(&pdev->dev)((&pdev->dev)->node); | ||||||||
| 430 | if (!dhandle) | ||||||||
| 431 | continue; | ||||||||
| 432 | |||||||||
| 433 | status = acpi_get_handle(dhandle, "ATRM", &atrm_handle); | ||||||||
| 434 | if (ACPI_SUCCESS(status)((status) == 0)) { | ||||||||
| 435 | found = true1; | ||||||||
| 436 | break; | ||||||||
| 437 | } | ||||||||
| 438 | } | ||||||||
| 439 | } | ||||||||
| 440 | #else | ||||||||
| 441 | { | ||||||||
| 442 | pdev = adev->pdev; | ||||||||
| 443 | dhandle = ACPI_HANDLE(&pdev->dev)((&pdev->dev)->node); | ||||||||
| 444 | |||||||||
| 445 | if (dhandle) { | ||||||||
| 446 | status = acpi_get_handle(dhandle, "ATRM", &atrm_handle); | ||||||||
| 447 | if (ACPI_SUCCESS(status)((status) == 0)) { | ||||||||
| 448 | found = true1; | ||||||||
| 449 | } | ||||||||
| 450 | } | ||||||||
| 451 | } | ||||||||
| 452 | #endif | ||||||||
| 453 | |||||||||
| 454 | if (!found
| ||||||||
| 455 | return false0; | ||||||||
| 456 | pci_dev_put(pdev); | ||||||||
| 457 | |||||||||
| 458 | adev->bios = kmalloc(size, GFP_KERNEL(0x0001 | 0x0004)); | ||||||||
| 459 | if (!adev->bios) { | ||||||||
| 460 | dev_err(adev->dev, "Unable to allocate bios\n")printf("drm:pid%d:%s *ERROR* " "Unable to allocate bios\n", ( {struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__); | ||||||||
| 461 | return false0; | ||||||||
| 462 | } | ||||||||
| 463 | |||||||||
| 464 | for (i = 0; i < size / ATRM_BIOS_PAGE4096; i++) { | ||||||||
| 465 | ret = amdgpu_atrm_call(atrm_handle, | ||||||||
| 466 | adev->bios, | ||||||||
| 467 | (i * ATRM_BIOS_PAGE4096), | ||||||||
| 468 | ATRM_BIOS_PAGE4096); | ||||||||
| 469 | if (ret
| ||||||||
| 470 | break; | ||||||||
| 471 | } | ||||||||
| 472 | |||||||||
| 473 | if (!check_atom_bios(adev->bios, size)) { | ||||||||
| 474 | kfree(adev->bios); | ||||||||
| 475 | return false0; | ||||||||
| 476 | } | ||||||||
| 477 | adev->bios_size = size; | ||||||||
| 478 | return true1; | ||||||||
| 479 | } | ||||||||
| 480 | #else | ||||||||
| 481 | static inline bool_Bool amdgpu_atrm_get_bios(struct amdgpu_device *adev) | ||||||||
| 482 | { | ||||||||
| 483 | return false0; | ||||||||
| 484 | } | ||||||||
| 485 | #endif | ||||||||
| 486 | |||||||||
| 487 | static bool_Bool amdgpu_read_disabled_bios(struct amdgpu_device *adev) | ||||||||
| 488 | { | ||||||||
| 489 | if (adev->flags & AMD_IS_APU) | ||||||||
| 490 | return igp_read_bios_from_vram(adev); | ||||||||
| 491 | else | ||||||||
| 492 | return (!adev->asic_funcs || !adev->asic_funcs->read_disabled_bios) ? | ||||||||
| 493 | false0 : amdgpu_asic_read_disabled_bios(adev)(adev)->asic_funcs->read_disabled_bios((adev)); | ||||||||
| 494 | } | ||||||||
| 495 | |||||||||
| 496 | #ifdef CONFIG_ACPI1 | ||||||||
| 497 | static bool_Bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev) | ||||||||
| 498 | { | ||||||||
| 499 | struct acpi_table_header *hdr; | ||||||||
| 500 | acpi_size tbl_size; | ||||||||
| 501 | UEFI_ACPI_VFCT *vfct; | ||||||||
| 502 | unsigned offset; | ||||||||
| 503 | |||||||||
| 504 | if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr))((acpi_get_table("VFCT", 1, &hdr)) == 0)) | ||||||||
| 505 | return false0; | ||||||||
| 506 | tbl_size = hdr->length; | ||||||||
| 507 | if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { | ||||||||
| 508 | dev_info(adev->dev, "ACPI VFCT table present but broken (too short #1),skipping\n")do { } while(0); | ||||||||
| 509 | return false0; | ||||||||
| 510 | } | ||||||||
| 511 | |||||||||
| 512 | vfct = (UEFI_ACPI_VFCT *)hdr; | ||||||||
| 513 | offset = vfct->VBIOSImageOffset; | ||||||||
| 514 | |||||||||
| 515 | while (offset < tbl_size) { | ||||||||
| 516 | GOP_VBIOS_CONTENT *vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + offset); | ||||||||
| 517 | VFCT_IMAGE_HEADER *vhdr = &vbios->VbiosHeader; | ||||||||
| 518 | |||||||||
| 519 | offset += sizeof(VFCT_IMAGE_HEADER); | ||||||||
| 520 | if (offset > tbl_size) { | ||||||||
| 521 | dev_info(adev->dev, "ACPI VFCT image header truncated,skipping\n")do { } while(0); | ||||||||
| 522 | return false0; | ||||||||
| 523 | } | ||||||||
| 524 | |||||||||
| 525 | offset += vhdr->ImageLength; | ||||||||
| 526 | if (offset > tbl_size) { | ||||||||
| 527 | dev_info(adev->dev, "ACPI VFCT image truncated,skipping\n")do { } while(0); | ||||||||
| 528 | return false0; | ||||||||
| 529 | } | ||||||||
| 530 | |||||||||
| 531 | if (vhdr->ImageLength && | ||||||||
| 532 | vhdr->PCIBus == adev->pdev->bus->number && | ||||||||
| 533 | vhdr->PCIDevice == PCI_SLOT(adev->pdev->devfn)((adev->pdev->devfn) >> 3) && | ||||||||
| 534 | vhdr->PCIFunction == PCI_FUNC(adev->pdev->devfn)((adev->pdev->devfn) & 0x7) && | ||||||||
| 535 | vhdr->VendorID == adev->pdev->vendor && | ||||||||
| 536 | vhdr->DeviceID == adev->pdev->device) { | ||||||||
| 537 | adev->bios = kmemdup(&vbios->VbiosContent, | ||||||||
| 538 | vhdr->ImageLength, | ||||||||
| 539 | GFP_KERNEL(0x0001 | 0x0004)); | ||||||||
| 540 | |||||||||
| 541 | if (!check_atom_bios(adev->bios, vhdr->ImageLength)) { | ||||||||
| 542 | kfree(adev->bios); | ||||||||
| 543 | return false0; | ||||||||
| 544 | } | ||||||||
| 545 | adev->bios_size = vhdr->ImageLength; | ||||||||
| 546 | return true1; | ||||||||
| 547 | } | ||||||||
| 548 | } | ||||||||
| 549 | |||||||||
| 550 | dev_info(adev->dev, "ACPI VFCT table present but broken (too short #2),skipping\n")do { } while(0); | ||||||||
| 551 | return false0; | ||||||||
| 552 | } | ||||||||
| 553 | #else | ||||||||
| 554 | static inline bool_Bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev) | ||||||||
| 555 | { | ||||||||
| 556 | return false0; | ||||||||
| 557 | } | ||||||||
| 558 | #endif | ||||||||
| 559 | |||||||||
| 560 | bool_Bool amdgpu_get_bios(struct amdgpu_device *adev) | ||||||||
| 561 | { | ||||||||
| 562 | if (amdgpu_atrm_get_bios(adev)) { | ||||||||
| |||||||||
| 563 | dev_info(adev->dev, "Fetched VBIOS from ATRM\n")do { } while(0); | ||||||||
| 564 | goto success; | ||||||||
| 565 | } | ||||||||
| 566 | |||||||||
| 567 | if (amdgpu_acpi_vfct_bios(adev)) { | ||||||||
| 568 | dev_info(adev->dev, "Fetched VBIOS from VFCT\n")do { } while(0); | ||||||||
| 569 | goto success; | ||||||||
| 570 | } | ||||||||
| 571 | |||||||||
| 572 | if (igp_read_bios_from_vram(adev)) { | ||||||||
| 573 | dev_info(adev->dev, "Fetched VBIOS from VRAM BAR\n")do { } while(0); | ||||||||
| 574 | goto success; | ||||||||
| 575 | } | ||||||||
| 576 | |||||||||
| 577 | if (amdgpu_read_bios(adev)) { | ||||||||
| 578 | dev_info(adev->dev, "Fetched VBIOS from ROM BAR\n")do { } while(0); | ||||||||
| 579 | goto success; | ||||||||
| 580 | } | ||||||||
| 581 | |||||||||
| 582 | if (amdgpu_read_bios_from_rom(adev)) { | ||||||||
| 583 | dev_info(adev->dev, "Fetched VBIOS from ROM\n")do { } while(0); | ||||||||
| 584 | goto success; | ||||||||
| 585 | } | ||||||||
| 586 | |||||||||
| 587 | if (amdgpu_read_disabled_bios(adev)) { | ||||||||
| 588 | dev_info(adev->dev, "Fetched VBIOS from disabled ROM BAR\n")do { } while(0); | ||||||||
| 589 | goto success; | ||||||||
| 590 | } | ||||||||
| 591 | |||||||||
| 592 | if (amdgpu_read_platform_bios(adev)) { | ||||||||
| 593 | dev_info(adev->dev, "Fetched VBIOS from platform\n")do { } while(0); | ||||||||
| 594 | goto success; | ||||||||
| 595 | } | ||||||||
| 596 | |||||||||
| 597 | dev_err(adev->dev, "Unable to locate a BIOS ROM\n")printf("drm:pid%d:%s *ERROR* " "Unable to locate a BIOS ROM\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__); | ||||||||
| 598 | return false0; | ||||||||
| 599 | |||||||||
| 600 | success: | ||||||||
| 601 | adev->is_atom_fw = (adev->asic_type >= CHIP_VEGA10) ? true1 : false0; | ||||||||
| 602 | return true1; | ||||||||
| 603 | } | ||||||||
| 604 | |||||||||
| 605 | /* helper function for soc15 and onwards to read bios from rom */ | ||||||||
| 606 | bool_Bool amdgpu_soc15_read_bios_from_rom(struct amdgpu_device *adev, | ||||||||
| 607 | u8 *bios, u32 length_bytes) | ||||||||
| 608 | { | ||||||||
| 609 | u32 *dw_ptr; | ||||||||
| 610 | u32 i, length_dw; | ||||||||
| 611 | u32 rom_offset; | ||||||||
| 612 | u32 rom_index_offset; | ||||||||
| 613 | u32 rom_data_offset; | ||||||||
| 614 | |||||||||
| 615 | if (bios == NULL((void *)0)) | ||||||||
| 616 | return false0; | ||||||||
| 617 | if (length_bytes == 0) | ||||||||
| 618 | return false0; | ||||||||
| 619 | /* APU vbios image is part of sbios image */ | ||||||||
| 620 | if (adev->flags & AMD_IS_APU) | ||||||||
| 621 | return false0; | ||||||||
| 622 | if (!adev->smuio.funcs || | ||||||||
| 623 | !adev->smuio.funcs->get_rom_index_offset || | ||||||||
| 624 | !adev->smuio.funcs->get_rom_data_offset) | ||||||||
| 625 | return false0; | ||||||||
| 626 | |||||||||
| 627 | dw_ptr = (u32 *)bios; | ||||||||
| 628 | length_dw = roundup2(length_bytes, 4)(((length_bytes) + ((4) - 1)) & (~((__typeof(length_bytes ))(4) - 1))) / 4; | ||||||||
| 629 | |||||||||
| 630 | rom_index_offset = | ||||||||
| 631 | adev->smuio.funcs->get_rom_index_offset(adev); | ||||||||
| 632 | rom_data_offset = | ||||||||
| 633 | adev->smuio.funcs->get_rom_data_offset(adev); | ||||||||
| 634 | |||||||||
| 635 | if (adev->nbio.funcs && | ||||||||
| 636 | adev->nbio.funcs->get_rom_offset) { | ||||||||
| 637 | rom_offset = adev->nbio.funcs->get_rom_offset(adev); | ||||||||
| 638 | rom_offset = rom_offset << 17; | ||||||||
| 639 | } else { | ||||||||
| 640 | rom_offset = 0; | ||||||||
| 641 | } | ||||||||
| 642 | |||||||||
| 643 | /* set rom index to rom_offset */ | ||||||||
| 644 | WREG32(rom_index_offset, rom_offset)amdgpu_device_wreg(adev, (rom_index_offset), (rom_offset), 0); | ||||||||
| 645 | /* read out the rom data */ | ||||||||
| 646 | for (i = 0; i < length_dw; i++) | ||||||||
| 647 | dw_ptr[i] = RREG32(rom_data_offset)amdgpu_device_rreg(adev, (rom_data_offset), 0); | ||||||||
| 648 | |||||||||
| 649 | return true1; | ||||||||
| 650 | } |
| 1 | /* Public domain. */ |
| 2 | |
| 3 | #ifndef _LINUX_SLAB_H |
| 4 | #define _LINUX_SLAB_H |
| 5 | |
| 6 | #include <sys/types.h> |
| 7 | #include <sys/malloc.h> |
| 8 | |
| 9 | #include <linux/types.h> |
| 10 | #include <linux/workqueue.h> |
| 11 | #include <linux/gfp.h> |
| 12 | |
| 13 | #include <linux/processor.h> /* for CACHELINESIZE */ |
| 14 | |
| 15 | #define ARCH_KMALLOC_MINALIGN64 CACHELINESIZE64 |
| 16 | |
| 17 | #define ZERO_SIZE_PTR((void *)0) NULL((void *)0) |
| 18 | |
| 19 | static inline void * |
| 20 | kmalloc(size_t size, int flags) |
| 21 | { |
| 22 | return malloc(size, M_DRM145, flags); |
| 23 | } |
| 24 | |
| 25 | static inline void * |
| 26 | kmalloc_array(size_t n, size_t size, int flags) |
| 27 | { |
| 28 | if (n != 0 && SIZE_MAX0xffffffffffffffffUL / n < size) |
| 29 | return NULL((void *)0); |
| 30 | return malloc(n * size, M_DRM145, flags); |
| 31 | } |
| 32 | |
| 33 | static inline void * |
| 34 | kcalloc(size_t n, size_t size, int flags) |
| 35 | { |
| 36 | if (n != 0 && SIZE_MAX0xffffffffffffffffUL / n < size) |
| 37 | return NULL((void *)0); |
| 38 | return malloc(n * size, M_DRM145, flags | M_ZERO0x0008); |
| 39 | } |
| 40 | |
| 41 | static inline void * |
| 42 | kzalloc(size_t size, int flags) |
| 43 | { |
| 44 | return malloc(size, M_DRM145, flags | M_ZERO0x0008); |
| 45 | } |
| 46 | |
| 47 | static inline void |
| 48 | kfree(const void *objp) |
| 49 | { |
| 50 | free((void *)objp, M_DRM145, 0); |
| 51 | } |
| 52 | |
| 53 | #endif |