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