LCOV - code coverage report
Current view: top level - drivers/gpu/drm/amd/amdgpu - amdgpu_bios.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 132 0.0 %
Date: 2022-12-09 01:23:36 Functions: 0 8 0.0 %

          Line data    Source code
       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             :  */
      49           0 : static bool check_atom_bios(uint8_t *bios, size_t size)
      50             : {
      51             :         uint16_t tmp, bios_header_start;
      52             : 
      53           0 :         if (!bios || size < 0x49) {
      54           0 :                 DRM_INFO("vbios mem is null or mem size is wrong\n");
      55           0 :                 return false;
      56             :         }
      57             : 
      58           0 :         if (!AMD_IS_VALID_VBIOS(bios)) {
      59           0 :                 DRM_INFO("BIOS signature incorrect %x %x\n", bios[0], bios[1]);
      60           0 :                 return false;
      61             :         }
      62             : 
      63           0 :         bios_header_start = bios[0x48] | (bios[0x49] << 8);
      64           0 :         if (!bios_header_start) {
      65           0 :                 DRM_INFO("Can't locate bios header\n");
      66           0 :                 return false;
      67             :         }
      68             : 
      69           0 :         tmp = bios_header_start + 4;
      70           0 :         if (size < tmp) {
      71           0 :                 DRM_INFO("BIOS header is broken\n");
      72           0 :                 return false;
      73             :         }
      74             : 
      75           0 :         if (!memcmp(bios + tmp, "ATOM", 4) ||
      76           0 :             !memcmp(bios + tmp, "MOTA", 4)) {
      77           0 :                 DRM_DEBUG("ATOMBIOS detected\n");
      78           0 :                 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             :  */
      90           0 : static bool igp_read_bios_from_vram(struct amdgpu_device *adev)
      91             : {
      92             :         uint8_t __iomem *bios;
      93             :         resource_size_t vram_base;
      94           0 :         resource_size_t size = 256 * 1024; /* ??? */
      95             : 
      96           0 :         if (!(adev->flags & AMD_IS_APU))
      97           0 :                 if (amdgpu_device_need_post(adev))
      98             :                         return false;
      99             : 
     100             :         /* FB BAR not enabled */
     101           0 :         if (pci_resource_len(adev->pdev, 0) == 0)
     102             :                 return false;
     103             : 
     104           0 :         adev->bios = NULL;
     105           0 :         vram_base = pci_resource_start(adev->pdev, 0);
     106           0 :         bios = ioremap_wc(vram_base, size);
     107           0 :         if (!bios) {
     108             :                 return false;
     109             :         }
     110             : 
     111           0 :         adev->bios = kmalloc(size, GFP_KERNEL);
     112           0 :         if (!adev->bios) {
     113           0 :                 iounmap(bios);
     114           0 :                 return false;
     115             :         }
     116           0 :         adev->bios_size = size;
     117           0 :         memcpy_fromio(adev->bios, bios, size);
     118           0 :         iounmap(bios);
     119             : 
     120           0 :         if (!check_atom_bios(adev->bios, size)) {
     121           0 :                 kfree(adev->bios);
     122           0 :                 return false;
     123             :         }
     124             : 
     125             :         return true;
     126             : }
     127             : 
     128           0 : bool amdgpu_read_bios(struct amdgpu_device *adev)
     129             : {
     130             :         uint8_t __iomem *bios;
     131             :         size_t size;
     132             : 
     133           0 :         adev->bios = NULL;
     134             :         /* XXX: some cards may return 0 for rom size? ddx has a workaround */
     135           0 :         bios = pci_map_rom(adev->pdev, &size);
     136           0 :         if (!bios) {
     137             :                 return false;
     138             :         }
     139             : 
     140           0 :         adev->bios = kzalloc(size, GFP_KERNEL);
     141           0 :         if (adev->bios == NULL) {
     142           0 :                 pci_unmap_rom(adev->pdev, bios);
     143           0 :                 return false;
     144             :         }
     145           0 :         adev->bios_size = size;
     146           0 :         memcpy_fromio(adev->bios, bios, size);
     147           0 :         pci_unmap_rom(adev->pdev, bios);
     148             : 
     149           0 :         if (!check_atom_bios(adev->bios, size)) {
     150           0 :                 kfree(adev->bios);
     151           0 :                 return false;
     152             :         }
     153             : 
     154             :         return true;
     155             : }
     156             : 
     157           0 : static bool amdgpu_read_bios_from_rom(struct amdgpu_device *adev)
     158             : {
     159           0 :         u8 header[AMD_VBIOS_SIGNATURE_END+1] = {0};
     160             :         int len;
     161             : 
     162           0 :         if (!adev->asic_funcs || !adev->asic_funcs->read_bios_from_rom)
     163             :                 return false;
     164             : 
     165             :         /* validate VBIOS signature */
     166           0 :         if (amdgpu_asic_read_bios_from_rom(adev, &header[0], sizeof(header)) == false)
     167             :                 return false;
     168           0 :         header[AMD_VBIOS_SIGNATURE_END] = 0;
     169             : 
     170           0 :         if ((!AMD_IS_VALID_VBIOS(header)) ||
     171           0 :             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           0 :         len = AMD_VBIOS_LENGTH(header);
     178           0 :         len = ALIGN(len, 4);
     179           0 :         adev->bios = kmalloc(len, GFP_KERNEL);
     180           0 :         if (!adev->bios) {
     181           0 :                 DRM_ERROR("no memory to allocate for BIOS\n");
     182           0 :                 return false;
     183             :         }
     184           0 :         adev->bios_size = len;
     185             : 
     186             :         /* read complete BIOS */
     187           0 :         amdgpu_asic_read_bios_from_rom(adev, adev->bios, len);
     188             : 
     189           0 :         if (!check_atom_bios(adev->bios, len)) {
     190           0 :                 kfree(adev->bios);
     191           0 :                 return false;
     192             :         }
     193             : 
     194             :         return true;
     195             : }
     196             : 
     197           0 : static bool amdgpu_read_platform_bios(struct amdgpu_device *adev)
     198             : {
     199           0 :         phys_addr_t rom = adev->pdev->rom;
     200           0 :         size_t romlen = adev->pdev->romlen;
     201             :         void __iomem *bios;
     202             : 
     203           0 :         adev->bios = NULL;
     204             : 
     205           0 :         if (!rom || romlen == 0)
     206             :                 return false;
     207             : 
     208           0 :         adev->bios = kzalloc(romlen, GFP_KERNEL);
     209           0 :         if (!adev->bios)
     210             :                 return false;
     211             : 
     212           0 :         bios = ioremap(rom, romlen);
     213           0 :         if (!bios)
     214             :                 goto free_bios;
     215             : 
     216           0 :         memcpy_fromio(adev->bios, bios, romlen);
     217           0 :         iounmap(bios);
     218             : 
     219           0 :         if (!check_atom_bios(adev->bios, romlen))
     220             :                 goto free_bios;
     221             : 
     222           0 :         adev->bios_size = romlen;
     223             : 
     224           0 :         return true;
     225             : free_bios:
     226           0 :         kfree(adev->bios);
     227           0 :         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             :  */
     248             : static 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             : 
     278             : static 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
     344             : static inline bool amdgpu_atrm_get_bios(struct amdgpu_device *adev)
     345             : {
     346             :         return false;
     347             : }
     348             : #endif
     349             : 
     350           0 : static bool amdgpu_read_disabled_bios(struct amdgpu_device *adev)
     351             : {
     352           0 :         if (adev->flags & AMD_IS_APU)
     353           0 :                 return igp_read_bios_from_vram(adev);
     354             :         else
     355           0 :                 return (!adev->asic_funcs || !adev->asic_funcs->read_disabled_bios) ?
     356           0 :                         false : amdgpu_asic_read_disabled_bios(adev);
     357             : }
     358             : 
     359             : #ifdef CONFIG_ACPI
     360             : static 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
     417             : static inline bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
     418             : {
     419             :         return false;
     420             : }
     421             : #endif
     422             : 
     423           0 : bool amdgpu_get_bios(struct amdgpu_device *adev)
     424             : {
     425           0 :         if (amdgpu_atrm_get_bios(adev)) {
     426             :                 dev_info(adev->dev, "Fetched VBIOS from ATRM\n");
     427             :                 goto success;
     428             :         }
     429             : 
     430           0 :         if (amdgpu_acpi_vfct_bios(adev)) {
     431             :                 dev_info(adev->dev, "Fetched VBIOS from VFCT\n");
     432             :                 goto success;
     433             :         }
     434             : 
     435           0 :         if (igp_read_bios_from_vram(adev)) {
     436           0 :                 dev_info(adev->dev, "Fetched VBIOS from VRAM BAR\n");
     437           0 :                 goto success;
     438             :         }
     439             : 
     440           0 :         if (amdgpu_read_bios(adev)) {
     441           0 :                 dev_info(adev->dev, "Fetched VBIOS from ROM BAR\n");
     442           0 :                 goto success;
     443             :         }
     444             : 
     445           0 :         if (amdgpu_read_bios_from_rom(adev)) {
     446           0 :                 dev_info(adev->dev, "Fetched VBIOS from ROM\n");
     447           0 :                 goto success;
     448             :         }
     449             : 
     450           0 :         if (amdgpu_read_disabled_bios(adev)) {
     451           0 :                 dev_info(adev->dev, "Fetched VBIOS from disabled ROM BAR\n");
     452           0 :                 goto success;
     453             :         }
     454             : 
     455           0 :         if (amdgpu_read_platform_bios(adev)) {
     456           0 :                 dev_info(adev->dev, "Fetched VBIOS from platform\n");
     457           0 :                 goto success;
     458             :         }
     459             : 
     460           0 :         dev_err(adev->dev, "Unable to locate a BIOS ROM\n");
     461           0 :         return false;
     462             : 
     463             : success:
     464           0 :         adev->is_atom_fw = (adev->asic_type >= CHIP_VEGA10) ? true : false;
     465           0 :         return true;
     466             : }
     467             : 
     468             : /* helper function for soc15 and onwards to read bios from rom */
     469           0 : bool amdgpu_soc15_read_bios_from_rom(struct amdgpu_device *adev,
     470             :                                      u8 *bios, u32 length_bytes)
     471             : {
     472             :         u32 *dw_ptr;
     473             :         u32 i, length_dw;
     474             :         u32 rom_offset;
     475             :         u32 rom_index_offset;
     476             :         u32 rom_data_offset;
     477             : 
     478           0 :         if (bios == NULL)
     479             :                 return false;
     480           0 :         if (length_bytes == 0)
     481             :                 return false;
     482             :         /* APU vbios image is part of sbios image */
     483           0 :         if (adev->flags & AMD_IS_APU)
     484             :                 return false;
     485           0 :         if (!adev->smuio.funcs ||
     486           0 :             !adev->smuio.funcs->get_rom_index_offset ||
     487           0 :             !adev->smuio.funcs->get_rom_data_offset)
     488             :                 return false;
     489             : 
     490           0 :         dw_ptr = (u32 *)bios;
     491           0 :         length_dw = ALIGN(length_bytes, 4) / 4;
     492             : 
     493           0 :         rom_index_offset =
     494             :                 adev->smuio.funcs->get_rom_index_offset(adev);
     495           0 :         rom_data_offset =
     496           0 :                 adev->smuio.funcs->get_rom_data_offset(adev);
     497             : 
     498           0 :         if (adev->nbio.funcs &&
     499           0 :             adev->nbio.funcs->get_rom_offset) {
     500           0 :                 rom_offset = adev->nbio.funcs->get_rom_offset(adev);
     501           0 :                 rom_offset = rom_offset << 17;
     502             :         } else {
     503             :                 rom_offset = 0;
     504             :         }
     505             : 
     506             :         /* set rom index to rom_offset */
     507           0 :         WREG32(rom_index_offset, rom_offset);
     508             :         /* read out the rom data */
     509           0 :         for (i = 0; i < length_dw; i++)
     510           0 :                 dw_ptr[i] = RREG32(rom_data_offset);
     511             : 
     512             :         return true;
     513             : }

Generated by: LCOV version 1.14