]>
Commit | Line | Data |
---|---|---|
72e0642f AC |
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 | */ | |
41 | static void * | |
42 | ls_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 | */ | |
92 | static int | |
93 | ls_ucode_img_load_gr(const struct nvkm_subdev *subdev, struct ls_ucode_img *img, | |
9d896f3e | 94 | const char *falcon_name) |
72e0642f | 95 | { |
9d896f3e | 96 | const struct firmware *bl, *code, *data, *sig; |
72e0642f AC |
97 | char f[64]; |
98 | int ret; | |
99 | ||
72e0642f AC |
100 | snprintf(f, sizeof(f), "gr/%s_bl", falcon_name); |
101 | ret = nvkm_firmware_get(subdev->device, 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->device, 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->device, f, &data); | |
112 | if (ret) | |
113 | goto free_inst; | |
114 | ||
9d896f3e AC |
115 | snprintf(f, sizeof(f), "gr/%s_sig", falcon_name); |
116 | ret = nvkm_firmware_get(subdev->device, f, &sig); | |
117 | if (ret) | |
118 | goto free_data; | |
563ad2b6 | 119 | |
9d896f3e AC |
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 | ||
72e0642f AC |
127 | img->ucode_data = ls_ucode_img_build(bl, code, data, |
128 | &img->ucode_desc); | |
129 | if (IS_ERR(img->ucode_data)) { | |
563ad2b6 | 130 | kfree(img->sig); |
72e0642f | 131 | ret = PTR_ERR(img->ucode_data); |
563ad2b6 | 132 | goto free_sig; |
72e0642f AC |
133 | } |
134 | img->ucode_size = img->ucode_desc.image_size; | |
135 | ||
9d896f3e AC |
136 | free_sig: |
137 | nvkm_firmware_put(sig); | |
72e0642f AC |
138 | free_data: |
139 | nvkm_firmware_put(data); | |
140 | free_inst: | |
141 | nvkm_firmware_put(code); | |
142 | free_bl: | |
143 | nvkm_firmware_put(bl); | |
144 | error: | |
145 | return ret; | |
146 | } | |
147 | ||
148 | int | |
2963a06a | 149 | acr_ls_ucode_load_fecs(const struct nvkm_secboot *sb, struct ls_ucode_img *img) |
72e0642f | 150 | { |
2963a06a | 151 | return ls_ucode_img_load_gr(&sb->subdev, img, "fecs"); |
72e0642f AC |
152 | } |
153 | ||
154 | int | |
2963a06a | 155 | acr_ls_ucode_load_gpccs(const struct nvkm_secboot *sb, struct ls_ucode_img *img) |
72e0642f | 156 | { |
2963a06a | 157 | return ls_ucode_img_load_gr(&sb->subdev, img, "gpccs"); |
72e0642f | 158 | } |