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        /* FB BAR not enabled */
 101        if (pci_resource_len(adev->pdev, 0) == 0)
 102                return false;
 103
 104        adev->bios = NULL;
 105        vram_base = pci_resource_start(adev->pdev, 0);
 106        bios = ioremap_wc(vram_base, size);
 107        if (!bios) {
 108                return false;
 109        }
 110
 111        adev->bios = kmalloc(size, GFP_KERNEL);
 112        if (!adev->bios) {
 113                iounmap(bios);
 114                return false;
 115        }
 116        adev->bios_size = size;
 117        memcpy_fromio(adev->bios, bios, size);
 118        iounmap(bios);
 119
 120        if (!check_atom_bios(adev->bios, size)) {
 121                kfree(adev->bios);
 122                return false;
 123        }
 124
 125        return true;
 126}
 127
 128bool amdgpu_read_bios(struct amdgpu_device *adev)
 129{
 130        uint8_t __iomem *bios;
 131        size_t size;
 132
 133        adev->bios = NULL;
 134        /* XXX: some cards may return 0 for rom size? ddx has a workaround */
 135        bios = pci_map_rom(adev->pdev, &size);
 136        if (!bios) {
 137                return false;
 138        }
 139
 140        adev->bios = kzalloc(size, GFP_KERNEL);
 141        if (adev->bios == NULL) {
 142                pci_unmap_rom(adev->pdev, bios);
 143                return false;
 144        }
 145        adev->bios_size = size;
 146        memcpy_fromio(adev->bios, bios, size);
 147        pci_unmap_rom(adev->pdev, bios);
 148
 149        if (!check_atom_bios(adev->bios, size)) {
 150                kfree(adev->bios);
 151                return false;
 152        }
 153
 154        return true;
 155}
 156
 157static bool amdgpu_read_bios_from_rom(struct amdgpu_device *adev)
 158{
 159        u8 header[AMD_VBIOS_SIGNATURE_END+1] = {0};
 160        int len;
 161
 162        if (!adev->asic_funcs || !adev->asic_funcs->read_bios_from_rom)
 163                return false;
 164
 165        /* validate VBIOS signature */
 166        if (amdgpu_asic_read_bios_from_rom(adev, &header[0], sizeof(header)) == false)
 167                return false;
 168        header[AMD_VBIOS_SIGNATURE_END] = 0;
 169
 170        if ((!AMD_IS_VALID_VBIOS(header)) ||
 171            0 != memcmp((char *)&header[AMD_VBIOS_SIGNATURE_OFFSET],
 172                        AMD_VBIOS_SIGNATURE,
 173                        strlen(AMD_VBIOS_SIGNATURE)))
 174                return false;
 175
 176        /* valid vbios, go on */
 177        len = AMD_VBIOS_LENGTH(header);
 178        len = ALIGN(len, 4);
 179        adev->bios = kmalloc(len, GFP_KERNEL);
 180        if (!adev->bios) {
 181                DRM_ERROR("no memory to allocate for BIOS\n");
 182                return false;
 183        }
 184        adev->bios_size = len;
 185
 186        /* read complete BIOS */
 187        amdgpu_asic_read_bios_from_rom(adev, adev->bios, len);
 188
 189        if (!check_atom_bios(adev->bios, len)) {
 190                kfree(adev->bios);
 191                return false;
 192        }
 193
 194        return true;
 195}
 196
 197static bool amdgpu_read_platform_bios(struct amdgpu_device *adev)
 198{
 199        phys_addr_t rom = adev->pdev->rom;
 200        size_t romlen = adev->pdev->romlen;
 201        void __iomem *bios;
 202
 203        adev->bios = NULL;
 204
 205        if (!rom || romlen == 0)
 206                return false;
 207
 208        adev->bios = kzalloc(romlen, GFP_KERNEL);
 209        if (!adev->bios)
 210                return false;
 211
 212        bios = ioremap(rom, romlen);
 213        if (!bios)
 214                goto free_bios;
 215
 216        memcpy_fromio(adev->bios, bios, romlen);
 217        iounmap(bios);
 218
 219        if (!check_atom_bios(adev->bios, romlen))
 220                goto free_bios;
 221
 222        adev->bios_size = romlen;
 223
 224        return true;
 225free_bios:
 226        kfree(adev->bios);
 227        return false;
 228}
 229
 230#ifdef CONFIG_ACPI
 231/* ATRM is used to get the BIOS on the discrete cards in
 232 * dual-gpu systems.
 233 */
 234/* retrieve the ROM in 4k blocks */
 235#define ATRM_BIOS_PAGE 4096
 236/**
 237 * amdgpu_atrm_call - fetch a chunk of the vbios
 238 *
 239 * @atrm_handle: acpi ATRM handle
 240 * @bios: vbios image pointer
 241 * @offset: offset of vbios image data to fetch
 242 * @len: length of vbios image data to fetch
 243 *
 244 * Executes ATRM to fetch a chunk of the discrete
 245 * vbios image on PX systems (all asics).
 246 * Returns the length of the buffer fetched.
 247 */
 248static int amdgpu_atrm_call(acpi_handle atrm_handle, uint8_t *bios,
 249                            int offset, int len)
 250{
 251        acpi_status status;
 252        union acpi_object atrm_arg_elements[2], *obj;
 253        struct acpi_object_list atrm_arg;
 254        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};
 255
 256        atrm_arg.count = 2;
 257        atrm_arg.pointer = &atrm_arg_elements[0];
 258
 259        atrm_arg_elements[0].type = ACPI_TYPE_INTEGER;
 260        atrm_arg_elements[0].integer.value = offset;
 261
 262        atrm_arg_elements[1].type = ACPI_TYPE_INTEGER;
 263        atrm_arg_elements[1].integer.value = len;
 264
 265        status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer);
 266        if (ACPI_FAILURE(status)) {
 267                printk("failed to evaluate ATRM got %s\n", acpi_format_exception(status));
 268                return -ENODEV;
 269        }
 270
 271        obj = (union acpi_object *)buffer.pointer;
 272        memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length);
 273        len = obj->buffer.length;
 274        kfree(buffer.pointer);
 275        return len;
 276}
 277
 278static bool amdgpu_atrm_get_bios(struct amdgpu_device *adev)
 279{
 280        int ret;
 281        int size = 256 * 1024;
 282        int i;
 283        struct pci_dev *pdev = NULL;
 284        acpi_handle dhandle, atrm_handle;
 285        acpi_status status;
 286        bool found = false;
 287
 288        /* ATRM is for the discrete card only */
 289        if (adev->flags & AMD_IS_APU)
 290                return false;
 291
 292        while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
 293                dhandle = ACPI_HANDLE(&pdev->dev);
 294                if (!dhandle)
 295                        continue;
 296
 297                status = acpi_get_handle(dhandle, "ATRM", &atrm_handle);
 298                if (ACPI_SUCCESS(status)) {
 299                        found = true;
 300                        break;
 301                }
 302        }
 303
 304        if (!found) {
 305                while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) {
 306                        dhandle = ACPI_HANDLE(&pdev->dev);
 307                        if (!dhandle)
 308                                continue;
 309
 310                        status = acpi_get_handle(dhandle, "ATRM", &atrm_handle);
 311                        if (ACPI_SUCCESS(status)) {
 312                                found = true;
 313                                break;
 314                        }
 315                }
 316        }
 317
 318        if (!found)
 319                return false;
 320
 321        adev->bios = kmalloc(size, GFP_KERNEL);
 322        if (!adev->bios) {
 323                dev_err(adev->dev, "Unable to allocate bios\n");
 324                return false;
 325        }
 326
 327        for (i = 0; i < size / ATRM_BIOS_PAGE; i++) {
 328                ret = amdgpu_atrm_call(atrm_handle,
 329                                       adev->bios,
 330                                       (i * ATRM_BIOS_PAGE),
 331                                       ATRM_BIOS_PAGE);
 332                if (ret < ATRM_BIOS_PAGE)
 333                        break;
 334        }
 335
 336        if (!check_atom_bios(adev->bios, size)) {
 337                kfree(adev->bios);
 338                return false;
 339        }
 340        adev->bios_size = size;
 341        return true;
 342}
 343#else
 344static inline bool amdgpu_atrm_get_bios(struct amdgpu_device *adev)
 345{
 346        return false;
 347}
 348#endif
 349
 350static bool amdgpu_read_disabled_bios(struct amdgpu_device *adev)
 351{
 352        if (adev->flags & AMD_IS_APU)
 353                return igp_read_bios_from_vram(adev);
 354        else
 355                return (!adev->asic_funcs || !adev->asic_funcs->read_disabled_bios) ?
 356                        false : amdgpu_asic_read_disabled_bios(adev);
 357}
 358
 359#ifdef CONFIG_ACPI
 360static bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
 361{
 362        struct acpi_table_header *hdr;
 363        acpi_size tbl_size;
 364        UEFI_ACPI_VFCT *vfct;
 365        unsigned offset;
 366
 367        if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr)))
 368                return false;
 369        tbl_size = hdr->length;
 370        if (tbl_size < sizeof(UEFI_ACPI_VFCT)) {
 371                dev_info(adev->dev, "ACPI VFCT table present but broken (too short #1),skipping\n");
 372                return false;
 373        }
 374
 375        vfct = (UEFI_ACPI_VFCT *)hdr;
 376        offset = vfct->VBIOSImageOffset;
 377
 378        while (offset < tbl_size) {
 379                GOP_VBIOS_CONTENT *vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + offset);
 380                VFCT_IMAGE_HEADER *vhdr = &vbios->VbiosHeader;
 381
 382                offset += sizeof(VFCT_IMAGE_HEADER);
 383                if (offset > tbl_size) {
 384                        dev_info(adev->dev, "ACPI VFCT image header truncated,skipping\n");
 385                        return false;
 386                }
 387
 388                offset += vhdr->ImageLength;
 389                if (offset > tbl_size) {
 390                        dev_info(adev->dev, "ACPI VFCT image truncated,skipping\n");
 391                        return false;
 392                }
 393
 394                if (vhdr->ImageLength &&
 395                    vhdr->PCIBus == adev->pdev->bus->number &&
 396                    vhdr->PCIDevice == PCI_SLOT(adev->pdev->devfn) &&
 397                    vhdr->PCIFunction == PCI_FUNC(adev->pdev->devfn) &&
 398                    vhdr->VendorID == adev->pdev->vendor &&
 399                    vhdr->DeviceID == adev->pdev->device) {
 400                        adev->bios = kmemdup(&vbios->VbiosContent,
 401                                             vhdr->ImageLength,
 402                                             GFP_KERNEL);
 403
 404                        if (!check_atom_bios(adev->bios, vhdr->ImageLength)) {
 405                                kfree(adev->bios);
 406                                return false;
 407                        }
 408                        adev->bios_size = vhdr->ImageLength;
 409                        return true;
 410                }
 411        }
 412
 413        dev_info(adev->dev, "ACPI VFCT table present but broken (too short #2),skipping\n");
 414        return false;
 415}
 416#else
 417static inline bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
 418{
 419        return false;
 420}
 421#endif
 422
 423bool amdgpu_get_bios(struct amdgpu_device *adev)
 424{
 425        if (amdgpu_atrm_get_bios(adev)) {
 426                dev_info(adev->dev, "Fetched VBIOS from ATRM\n");
 427                goto success;
 428        }
 429
 430        if (amdgpu_acpi_vfct_bios(adev)) {
 431                dev_info(adev->dev, "Fetched VBIOS from VFCT\n");
 432                goto success;
 433        }
 434
 435        if (igp_read_bios_from_vram(adev)) {
 436                dev_info(adev->dev, "Fetched VBIOS from VRAM BAR\n");
 437                goto success;
 438        }
 439
 440        if (amdgpu_read_bios(adev)) {
 441                dev_info(adev->dev, "Fetched VBIOS from ROM BAR\n");
 442                goto success;
 443        }
 444
 445        if (amdgpu_read_bios_from_rom(adev)) {
 446                dev_info(adev->dev, "Fetched VBIOS from ROM\n");
 447                goto success;
 448        }
 449
 450        if (amdgpu_read_disabled_bios(adev)) {
 451                dev_info(adev->dev, "Fetched VBIOS from disabled ROM BAR\n");
 452                goto success;
 453        }
 454
 455        if (amdgpu_read_platform_bios(adev)) {
 456                dev_info(adev->dev, "Fetched VBIOS from platform\n");
 457                goto success;
 458        }
 459
 460        dev_err(adev->dev, "Unable to locate a BIOS ROM\n");
 461        return false;
 462
 463success:
 464        adev->is_atom_fw = (adev->asic_type >= CHIP_VEGA10) ? true : false;
 465        return true;
 466}
 467