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