1 /* SPDX-License-Identifier: MIT */ 2 /* 3 * Copyright © 2014-2019 Intel Corporation 4 */ 5 6 #ifndef _INTEL_UC_FW_H_ 7 #define _INTEL_UC_FW_H_ 8 9 #include <linux/types.h> 10 #include "intel_uc_fw_abi.h" 11 #include "intel_device_info.h" 12 #include "i915_gem.h" 13 #include "i915_vma.h" 14 15 struct drm_printer; 16 struct drm_i915_private; 17 struct intel_gt; 18 19 /* Home of GuC, HuC and DMC firmwares */ 20 #define INTEL_UC_FIRMWARE_URL "https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/tree/i915" 21 22 /* 23 * +------------+---------------------------------------------------+ 24 * | PHASE | FIRMWARE STATUS TRANSITIONS | 25 * +============+===================================================+ 26 * | | UNINITIALIZED | 27 * +------------+- / | \ -+ 28 * | | DISABLED <--/ | \--> NOT_SUPPORTED | 29 * | init_early | V | 30 * | | SELECTED | 31 * +------------+- / | \ -+ 32 * | | MISSING <--/ | \--> ERROR | 33 * | fetch | V | 34 * | | AVAILABLE | 35 * +------------+- | -+ 36 * | init | V | 37 * | | /------> LOADABLE <----<-----------\ | 38 * +------------+- \ / \ \ \ -+ 39 * | | FAIL <--< \--> TRANSFERRED \ | 40 * | upload | \ / \ / | 41 * | | \---------/ \--> RUNNING | 42 * +------------+---------------------------------------------------+ 43 */ 44 45 enum intel_uc_fw_status { 46 INTEL_UC_FIRMWARE_NOT_SUPPORTED = -1, /* no uc HW */ 47 INTEL_UC_FIRMWARE_UNINITIALIZED = 0, /* used to catch checks done too early */ 48 INTEL_UC_FIRMWARE_DISABLED, /* disabled */ 49 INTEL_UC_FIRMWARE_SELECTED, /* selected the blob we want to load */ 50 INTEL_UC_FIRMWARE_MISSING, /* blob not found on the system */ 51 INTEL_UC_FIRMWARE_ERROR, /* invalid format or version */ 52 INTEL_UC_FIRMWARE_AVAILABLE, /* blob found and copied in mem */ 53 INTEL_UC_FIRMWARE_LOADABLE, /* all fw-required objects are ready */ 54 INTEL_UC_FIRMWARE_FAIL, /* failed to xfer or init/auth the fw */ 55 INTEL_UC_FIRMWARE_TRANSFERRED, /* dma xfer done */ 56 INTEL_UC_FIRMWARE_RUNNING /* init/auth done */ 57 }; 58 59 enum intel_uc_fw_type { 60 INTEL_UC_FW_TYPE_GUC = 0, 61 INTEL_UC_FW_TYPE_HUC 62 }; 63 #define INTEL_UC_FW_NUM_TYPES 2 64 65 /* 66 * This structure encapsulates all the data needed during the process 67 * of fetching, caching, and loading the firmware image into the uC. 68 */ 69 struct intel_uc_fw { 70 enum intel_uc_fw_type type; 71 union { 72 const enum intel_uc_fw_status status; 73 enum intel_uc_fw_status __status; /* no accidental overwrites */ 74 }; 75 const char *path; 76 bool user_overridden; 77 size_t size; 78 struct drm_i915_gem_object *obj; 79 /** 80 * @dummy: A vma used in binding the uc fw to ggtt. We can't define this 81 * vma on the stack as it can lead to a stack overflow, so we define it 82 * here. Safe to have 1 copy per uc fw because the binding is single 83 * threaded as it done during driver load (inherently single threaded) 84 * or during a GT reset (mutex guarantees single threaded). 85 */ 86 struct i915_vma dummy; 87 88 /* 89 * The firmware build process will generate a version header file with major and 90 * minor version defined. The versions are built into CSS header of firmware. 91 * i915 kernel driver set the minimal firmware version required per platform. 92 */ 93 u16 major_ver_wanted; 94 u16 minor_ver_wanted; 95 u16 major_ver_found; 96 u16 minor_ver_found; 97 98 u32 rsa_size; 99 u32 ucode_size; 100 101 u32 private_data_size; 102 }; 103 104 #ifdef CONFIG_DRM_I915_DEBUG_GUC 105 void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw, 106 enum intel_uc_fw_status status); 107 #else 108 static inline void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw, 109 enum intel_uc_fw_status status) 110 { 111 uc_fw->__status = status; 112 } 113 #endif 114 115 static inline 116 const char *intel_uc_fw_status_repr(enum intel_uc_fw_status status) 117 { 118 switch (status) { 119 case INTEL_UC_FIRMWARE_NOT_SUPPORTED: 120 return "N/A"; 121 case INTEL_UC_FIRMWARE_UNINITIALIZED: 122 return "UNINITIALIZED"; 123 case INTEL_UC_FIRMWARE_DISABLED: 124 return "DISABLED"; 125 case INTEL_UC_FIRMWARE_SELECTED: 126 return "SELECTED"; 127 case INTEL_UC_FIRMWARE_MISSING: 128 return "MISSING"; 129 case INTEL_UC_FIRMWARE_ERROR: 130 return "ERROR"; 131 case INTEL_UC_FIRMWARE_AVAILABLE: 132 return "AVAILABLE"; 133 case INTEL_UC_FIRMWARE_LOADABLE: 134 return "LOADABLE"; 135 case INTEL_UC_FIRMWARE_FAIL: 136 return "FAIL"; 137 case INTEL_UC_FIRMWARE_TRANSFERRED: 138 return "TRANSFERRED"; 139 case INTEL_UC_FIRMWARE_RUNNING: 140 return "RUNNING"; 141 } 142 return "<invalid>"; 143 } 144 145 static inline int intel_uc_fw_status_to_error(enum intel_uc_fw_status status) 146 { 147 switch (status) { 148 case INTEL_UC_FIRMWARE_NOT_SUPPORTED: 149 return -ENODEV; 150 case INTEL_UC_FIRMWARE_UNINITIALIZED: 151 return -EACCES; 152 case INTEL_UC_FIRMWARE_DISABLED: 153 return -EPERM; 154 case INTEL_UC_FIRMWARE_MISSING: 155 return -ENOENT; 156 case INTEL_UC_FIRMWARE_ERROR: 157 return -ENOEXEC; 158 case INTEL_UC_FIRMWARE_FAIL: 159 return -EIO; 160 case INTEL_UC_FIRMWARE_SELECTED: 161 return -ESTALE; 162 case INTEL_UC_FIRMWARE_AVAILABLE: 163 case INTEL_UC_FIRMWARE_LOADABLE: 164 case INTEL_UC_FIRMWARE_TRANSFERRED: 165 case INTEL_UC_FIRMWARE_RUNNING: 166 return 0; 167 } 168 return -EINVAL; 169 } 170 171 static inline const char *intel_uc_fw_type_repr(enum intel_uc_fw_type type) 172 { 173 switch (type) { 174 case INTEL_UC_FW_TYPE_GUC: 175 return "GuC"; 176 case INTEL_UC_FW_TYPE_HUC: 177 return "HuC"; 178 } 179 return "uC"; 180 } 181 182 static inline enum intel_uc_fw_status 183 __intel_uc_fw_status(struct intel_uc_fw *uc_fw) 184 { 185 /* shouldn't call this before checking hw/blob availability */ 186 GEM_BUG_ON(uc_fw->status == INTEL_UC_FIRMWARE_UNINITIALIZED); 187 return uc_fw->status; 188 } 189 190 static inline bool intel_uc_fw_is_supported(struct intel_uc_fw *uc_fw) 191 { 192 return __intel_uc_fw_status(uc_fw) != INTEL_UC_FIRMWARE_NOT_SUPPORTED; 193 } 194 195 static inline bool intel_uc_fw_is_enabled(struct intel_uc_fw *uc_fw) 196 { 197 return __intel_uc_fw_status(uc_fw) > INTEL_UC_FIRMWARE_DISABLED; 198 } 199 200 static inline bool intel_uc_fw_is_available(struct intel_uc_fw *uc_fw) 201 { 202 return __intel_uc_fw_status(uc_fw) >= INTEL_UC_FIRMWARE_AVAILABLE; 203 } 204 205 static inline bool intel_uc_fw_is_loadable(struct intel_uc_fw *uc_fw) 206 { 207 return __intel_uc_fw_status(uc_fw) >= INTEL_UC_FIRMWARE_LOADABLE; 208 } 209 210 static inline bool intel_uc_fw_is_loaded(struct intel_uc_fw *uc_fw) 211 { 212 return __intel_uc_fw_status(uc_fw) >= INTEL_UC_FIRMWARE_TRANSFERRED; 213 } 214 215 static inline bool intel_uc_fw_is_running(struct intel_uc_fw *uc_fw) 216 { 217 return __intel_uc_fw_status(uc_fw) == INTEL_UC_FIRMWARE_RUNNING; 218 } 219 220 static inline bool intel_uc_fw_is_overridden(const struct intel_uc_fw *uc_fw) 221 { 222 return uc_fw->user_overridden; 223 } 224 225 static inline void intel_uc_fw_sanitize(struct intel_uc_fw *uc_fw) 226 { 227 if (intel_uc_fw_is_loaded(uc_fw)) 228 intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_LOADABLE); 229 } 230 231 static inline u32 __intel_uc_fw_get_upload_size(struct intel_uc_fw *uc_fw) 232 { 233 return sizeof(struct uc_css_header) + uc_fw->ucode_size; 234 } 235 236 /** 237 * intel_uc_fw_get_upload_size() - Get size of firmware needed to be uploaded. 238 * @uc_fw: uC firmware. 239 * 240 * Get the size of the firmware and header that will be uploaded to WOPCM. 241 * 242 * Return: Upload firmware size, or zero on firmware fetch failure. 243 */ 244 static inline u32 intel_uc_fw_get_upload_size(struct intel_uc_fw *uc_fw) 245 { 246 if (!intel_uc_fw_is_available(uc_fw)) 247 return 0; 248 249 return __intel_uc_fw_get_upload_size(uc_fw); 250 } 251 252 void intel_uc_fw_init_early(struct intel_uc_fw *uc_fw, 253 enum intel_uc_fw_type type); 254 int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw); 255 void intel_uc_fw_cleanup_fetch(struct intel_uc_fw *uc_fw); 256 int intel_uc_fw_upload(struct intel_uc_fw *uc_fw, u32 offset, u32 dma_flags); 257 int intel_uc_fw_init(struct intel_uc_fw *uc_fw); 258 void intel_uc_fw_fini(struct intel_uc_fw *uc_fw); 259 size_t intel_uc_fw_copy_rsa(struct intel_uc_fw *uc_fw, void *dst, u32 max_len); 260 void intel_uc_fw_dump(const struct intel_uc_fw *uc_fw, struct drm_printer *p); 261 262 #endif 263