2 * Copyright 2019 Red Hat Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
24 #include <core/firmware.h>
30 nvkm_acr_hsfw_del(struct nvkm_acr_hsfw
*hsfw
)
32 list_del(&hsfw
->head
);
35 kfree(hsfw
->sig
.prod
.data
);
36 kfree(hsfw
->sig
.dbg
.data
);
41 nvkm_acr_hsfw_del_all(struct nvkm_acr
*acr
)
43 struct nvkm_acr_hsfw
*hsfw
, *hsft
;
44 list_for_each_entry_safe(hsfw
, hsft
, &acr
->hsfw
, head
) {
45 nvkm_acr_hsfw_del(hsfw
);
50 nvkm_acr_hsfw_load_image(struct nvkm_acr
*acr
, const char *name
, int ver
,
51 struct nvkm_acr_hsfw
*hsfw
)
53 struct nvkm_subdev
*subdev
= &acr
->subdev
;
54 const struct firmware
*fw
;
55 const struct nvfw_bin_hdr
*hdr
;
56 const struct nvfw_hs_header
*fwhdr
;
57 const struct nvfw_hs_load_header
*lhdr
;
61 ret
= nvkm_firmware_get(subdev
, name
, ver
, &fw
);
65 hdr
= nvfw_bin_hdr(subdev
, fw
->data
);
66 fwhdr
= nvfw_hs_header(subdev
, fw
->data
+ hdr
->header_offset
);
68 /* Earlier FW releases by NVIDIA for Nouveau's use aren't in NVIDIA's
69 * standard format, and don't have the indirection seen in the 0x10de
72 switch (hdr
->bin_magic
) {
74 loc
= *(u32
*)(fw
->data
+ fwhdr
->patch_loc
);
75 sig
= *(u32
*)(fw
->data
+ fwhdr
->patch_sig
);
78 loc
= fwhdr
->patch_loc
;
79 sig
= fwhdr
->patch_sig
;
86 lhdr
= nvfw_hs_load_header(subdev
, fw
->data
+ fwhdr
->hdr_offset
);
88 if (!(hsfw
->image
= kmalloc(hdr
->data_size
, GFP_KERNEL
))) {
93 memcpy(hsfw
->image
, fw
->data
+ hdr
->data_offset
, hdr
->data_size
);
94 hsfw
->image_size
= hdr
->data_size
;
95 hsfw
->non_sec_addr
= lhdr
->non_sec_code_off
;
96 hsfw
->non_sec_size
= lhdr
->non_sec_code_size
;
97 hsfw
->sec_addr
= lhdr
->apps
[0];
98 hsfw
->sec_size
= lhdr
->apps
[lhdr
->num_apps
];
99 hsfw
->data_addr
= lhdr
->data_dma_base
;
100 hsfw
->data_size
= lhdr
->data_size
;
102 hsfw
->sig
.prod
.size
= fwhdr
->sig_prod_size
;
103 hsfw
->sig
.prod
.data
= kmalloc(hsfw
->sig
.prod
.size
, GFP_KERNEL
);
104 if (!hsfw
->sig
.prod
.data
) {
109 memcpy(hsfw
->sig
.prod
.data
, fw
->data
+ fwhdr
->sig_prod_offset
+ sig
,
110 hsfw
->sig
.prod
.size
);
112 hsfw
->sig
.dbg
.size
= fwhdr
->sig_dbg_size
;
113 hsfw
->sig
.dbg
.data
= kmalloc(hsfw
->sig
.dbg
.size
, GFP_KERNEL
);
114 if (!hsfw
->sig
.dbg
.data
) {
119 memcpy(hsfw
->sig
.dbg
.data
, fw
->data
+ fwhdr
->sig_dbg_offset
+ sig
,
122 hsfw
->sig
.patch_loc
= loc
;
124 nvkm_firmware_put(fw
);
129 nvkm_acr_hsfw_load_bl(struct nvkm_acr
*acr
, const char *name
, int ver
,
130 struct nvkm_acr_hsfw
*hsfw
)
132 struct nvkm_subdev
*subdev
= &acr
->subdev
;
133 const struct nvfw_bin_hdr
*hdr
;
134 const struct nvfw_bl_desc
*desc
;
135 const struct firmware
*fw
;
139 ret
= nvkm_firmware_get(subdev
, name
, ver
, &fw
);
143 hdr
= nvfw_bin_hdr(subdev
, fw
->data
);
144 desc
= nvfw_bl_desc(subdev
, fw
->data
+ hdr
->header_offset
);
145 data
= (void *)fw
->data
+ hdr
->data_offset
;
147 hsfw
->imem_size
= desc
->code_size
;
148 hsfw
->imem_tag
= desc
->start_tag
;
149 hsfw
->imem
= kmalloc(desc
->code_size
, GFP_KERNEL
);
150 memcpy(hsfw
->imem
, data
+ desc
->code_off
, desc
->code_size
);
152 nvkm_firmware_put(fw
);
157 nvkm_acr_hsfw_load(struct nvkm_acr
*acr
, const char *bl
, const char *fw
,
158 const char *name
, int version
,
159 const struct nvkm_acr_hsf_fwif
*fwif
)
161 struct nvkm_acr_hsfw
*hsfw
;
164 if (!(hsfw
= kzalloc(sizeof(*hsfw
), GFP_KERNEL
)))
167 hsfw
->func
= fwif
->func
;
169 list_add_tail(&hsfw
->head
, &acr
->hsfw
);
171 ret
= nvkm_acr_hsfw_load_bl(acr
, bl
, version
, hsfw
);
175 ret
= nvkm_acr_hsfw_load_image(acr
, fw
, version
, hsfw
);
178 nvkm_acr_hsfw_del(hsfw
);