linux/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_gr.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice shall be included in
  12 * all copies or substantial portions of the Software.
  13 *
  14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  20 * DEALINGS IN THE SOFTWARE.
  21 */
  22
  23
  24#include "ls_ucode.h"
  25#include "acr.h"
  26
  27#include <core/firmware.h>
  28
  29#define BL_DESC_BLK_SIZE 256
  30/**
  31 * Build a ucode image and descriptor from provided bootloader, code and data.
  32 *
  33 * @bl:         bootloader image, including 16-bytes descriptor
  34 * @code:       LS firmware code segment
  35 * @data:       LS firmware data segment
  36 * @desc:       ucode descriptor to be written
  37 *
  38 * Return: allocated ucode image with corresponding descriptor information. desc
  39 *         is also updated to contain the right offsets within returned image.
  40 */
  41static void *
  42ls_ucode_img_build(const struct firmware *bl, const struct firmware *code,
  43                   const struct firmware *data, struct ls_ucode_img_desc *desc)
  44{
  45        struct fw_bin_header *bin_hdr = (void *)bl->data;
  46        struct fw_bl_desc *bl_desc = (void *)bl->data + bin_hdr->header_offset;
  47        void *bl_data = (void *)bl->data + bin_hdr->data_offset;
  48        u32 pos = 0;
  49        void *image;
  50
  51        desc->bootloader_start_offset = pos;
  52        desc->bootloader_size = ALIGN(bl_desc->code_size, sizeof(u32));
  53        desc->bootloader_imem_offset = bl_desc->start_tag * 256;
  54        desc->bootloader_entry_point = bl_desc->start_tag * 256;
  55
  56        pos = ALIGN(pos + desc->bootloader_size, BL_DESC_BLK_SIZE);
  57        desc->app_start_offset = pos;
  58        desc->app_size = ALIGN(code->size, BL_DESC_BLK_SIZE) +
  59                         ALIGN(data->size, BL_DESC_BLK_SIZE);
  60        desc->app_imem_offset = 0;
  61        desc->app_imem_entry = 0;
  62        desc->app_dmem_offset = 0;
  63        desc->app_resident_code_offset = 0;
  64        desc->app_resident_code_size = ALIGN(code->size, BL_DESC_BLK_SIZE);
  65
  66        pos = ALIGN(pos + desc->app_resident_code_size, BL_DESC_BLK_SIZE);
  67        desc->app_resident_data_offset = pos - desc->app_start_offset;
  68        desc->app_resident_data_size = ALIGN(data->size, BL_DESC_BLK_SIZE);
  69
  70        desc->image_size = ALIGN(bl_desc->code_size, BL_DESC_BLK_SIZE) +
  71                           desc->app_size;
  72
  73        image = kzalloc(desc->image_size, GFP_KERNEL);
  74        if (!image)
  75                return ERR_PTR(-ENOMEM);
  76
  77        memcpy(image + desc->bootloader_start_offset, bl_data,
  78               bl_desc->code_size);
  79        memcpy(image + desc->app_start_offset, code->data, code->size);
  80        memcpy(image + desc->app_start_offset + desc->app_resident_data_offset,
  81               data->data, data->size);
  82
  83        return image;
  84}
  85
  86/**
  87 * ls_ucode_img_load_gr() - load and prepare a LS GR ucode image
  88 *
  89 * Load the LS microcode, bootloader and signature and pack them into a single
  90 * blob. Also generate the corresponding ucode descriptor.
  91 */
  92static int
  93ls_ucode_img_load_gr(const struct nvkm_subdev *subdev, int maxver,
  94                     struct ls_ucode_img *img, const char *falcon_name)
  95{
  96        const struct firmware *bl, *code, *data, *sig;
  97        char f[64];
  98        int ret;
  99
 100        snprintf(f, sizeof(f), "gr/%s_bl", falcon_name);
 101        ret = nvkm_firmware_get(subdev, f, &bl);
 102        if (ret)
 103                goto error;
 104
 105        snprintf(f, sizeof(f), "gr/%s_inst", falcon_name);
 106        ret = nvkm_firmware_get(subdev, f, &code);
 107        if (ret)
 108                goto free_bl;
 109
 110        snprintf(f, sizeof(f), "gr/%s_data", falcon_name);
 111        ret = nvkm_firmware_get(subdev, f, &data);
 112        if (ret)
 113                goto free_inst;
 114
 115        snprintf(f, sizeof(f), "gr/%s_sig", falcon_name);
 116        ret = nvkm_firmware_get(subdev, f, &sig);
 117        if (ret)
 118                goto free_data;
 119
 120        img->sig = kmemdup(sig->data, sig->size, GFP_KERNEL);
 121        if (!img->sig) {
 122                ret = -ENOMEM;
 123                goto free_sig;
 124        }
 125        img->sig_size = sig->size;
 126
 127        img->ucode_data = ls_ucode_img_build(bl, code, data,
 128                                             &img->ucode_desc);
 129        if (IS_ERR(img->ucode_data)) {
 130                kfree(img->sig);
 131                ret = PTR_ERR(img->ucode_data);
 132                goto free_sig;
 133        }
 134        img->ucode_size = img->ucode_desc.image_size;
 135
 136free_sig:
 137        nvkm_firmware_put(sig);
 138free_data:
 139        nvkm_firmware_put(data);
 140free_inst:
 141        nvkm_firmware_put(code);
 142free_bl:
 143        nvkm_firmware_put(bl);
 144error:
 145        return ret;
 146}
 147
 148int
 149acr_ls_ucode_load_fecs(const struct nvkm_secboot *sb, int maxver,
 150                       struct ls_ucode_img *img)
 151{
 152        return ls_ucode_img_load_gr(&sb->subdev, maxver, img, "fecs");
 153}
 154
 155int
 156acr_ls_ucode_load_gpccs(const struct nvkm_secboot *sb, int maxver,
 157                        struct ls_ucode_img *img)
 158{
 159        return ls_ucode_img_load_gr(&sb->subdev, maxver, img, "gpccs");
 160}
 161