#define FIRMWARE_DCN_401_DMUB "amdgpu/dcn_4_0_1_dmcub.bin"
MODULE_FIRMWARE(FIRMWARE_DCN_401_DMUB);
-/* Number of bytes in PSP header for firmware. */
-#define PSP_HEADER_BYTES 0x100
-
-/* Number of bytes in PSP footer for firmware. */
-#define PSP_FOOTER_BYTES 0x100
-
/**
* DOC: overview
*
fw_inst_const = dmub_fw->data +
le32_to_cpu(hdr->header.ucode_array_offset_bytes) +
- PSP_HEADER_BYTES;
+ PSP_HEADER_BYTES_256;
fw_bss_data = dmub_fw->data +
le32_to_cpu(hdr->header.ucode_array_offset_bytes) +
le32_to_cpu(hdr->inst_const_bytes);
/* Copy firmware and bios info into FB memory. */
- fw_inst_const_size = le32_to_cpu(hdr->inst_const_bytes) -
- PSP_HEADER_BYTES - PSP_FOOTER_BYTES;
+ fw_inst_const_size = adev->dm.fw_inst_size;
fw_bss_data_size = le32_to_cpu(hdr->bss_data_bytes);
static int dm_dmub_sw_init(struct amdgpu_device *adev)
{
struct dmub_srv_create_params create_params;
+ struct dmub_srv_fw_meta_info_params fw_meta_info_params;
struct dmub_srv_region_params region_params;
struct dmub_srv_region_info region_info;
struct dmub_srv_memory_params memory_params;
+ struct dmub_fw_meta_info fw_info;
struct dmub_srv_fb_info *fb_info;
struct dmub_srv *dmub_srv;
const struct dmcub_firmware_header_v1_0 *hdr;
return -EINVAL;
}
+ /* Extract the FW meta info. */
+ memset(&fw_meta_info_params, 0, sizeof(fw_meta_info_params));
+
+ fw_meta_info_params.inst_const_size = le32_to_cpu(hdr->inst_const_bytes) -
+ PSP_HEADER_BYTES_256;
+ fw_meta_info_params.bss_data_size = le32_to_cpu(hdr->bss_data_bytes);
+ fw_meta_info_params.fw_inst_const = adev->dm.dmub_fw->data +
+ le32_to_cpu(hdr->header.ucode_array_offset_bytes) +
+ PSP_HEADER_BYTES_256;
+ fw_meta_info_params.fw_bss_data = region_params.bss_data_size ? adev->dm.dmub_fw->data +
+ le32_to_cpu(hdr->header.ucode_array_offset_bytes) +
+ le32_to_cpu(hdr->inst_const_bytes) : NULL;
+ fw_meta_info_params.custom_psp_footer_size = 0;
+
+ status = dmub_srv_get_fw_meta_info_from_raw_fw(&fw_meta_info_params, &fw_info);
+ if (status != DMUB_STATUS_OK) {
+ /* Skip returning early, just log the error. */
+ drm_err(adev_to_drm(adev), "Error getting DMUB FW meta info: %d\n", status);
+ // return -EINVAL;
+ }
+
/* Calculate the size of all the regions for the DMUB service. */
memset(®ion_params, 0, sizeof(region_params));
- region_params.inst_const_size = le32_to_cpu(hdr->inst_const_bytes) -
- PSP_HEADER_BYTES - PSP_FOOTER_BYTES;
- region_params.bss_data_size = le32_to_cpu(hdr->bss_data_bytes);
+ region_params.inst_const_size = fw_meta_info_params.inst_const_size;
+ region_params.bss_data_size = fw_meta_info_params.bss_data_size;
region_params.vbios_size = adev->bios_size;
- region_params.fw_bss_data = region_params.bss_data_size ?
- adev->dm.dmub_fw->data +
- le32_to_cpu(hdr->header.ucode_array_offset_bytes) +
- le32_to_cpu(hdr->inst_const_bytes) : NULL;
- region_params.fw_inst_const =
- adev->dm.dmub_fw->data +
- le32_to_cpu(hdr->header.ucode_array_offset_bytes) +
- PSP_HEADER_BYTES;
+ region_params.fw_bss_data = fw_meta_info_params.fw_bss_data;
+ region_params.fw_inst_const = fw_meta_info_params.fw_inst_const;
region_params.window_memory_type = window_memory_type;
+ region_params.fw_info = (status == DMUB_STATUS_OK) ? &fw_info : NULL;
status = dmub_srv_calc_region_info(dmub_srv, ®ion_params,
®ion_info);
}
adev->dm.bb_from_dmub = dm_dmub_get_vbios_bounding_box(adev);
+ adev->dm.fw_inst_size = fw_meta_info_params.inst_const_size;
return 0;
}
*/
uint32_t dmcub_fw_version;
+ /**
+ * @fw_inst_size:
+ *
+ * Size of the firmware instruction buffer.
+ */
+ uint32_t fw_inst_size;
+
/**
* @cgs_device:
*
short auxless_alpm_lfps_t1t2_offset_us;
bool disable_stutter_for_wm_program;
bool enable_block_sequence_programming;
+ uint32_t custom_psp_footer_size;
};
/* Default tracebuffer size if meta is absent. */
#define DMUB_TRACE_BUFFER_SIZE (64 * 1024)
+#define PSP_HEADER_BYTES_256 0x100 // 256 bytes
+#define PSP_FOOTER_BYTES_256 0x100 // 256 bytes
+
/* Forward declarations */
struct dmub_srv;
struct dmub_srv_common_regs;
const uint8_t *fw_inst_const;
const uint8_t *fw_bss_data;
const enum dmub_window_memory_type *window_memory_type;
+ const struct dmub_fw_meta_info *fw_info;
+};
+
+/**
+ * struct dmub_srv_fw_meta_info_params - params used for fetching fw meta info from fw_image
+ * @inst_const_size: size of the fw inst const section
+ * @bss_data_size: size of the fw bss data section
+ * @fw_inst_const: raw firmware inst const section
+ * @fw_bss_data: raw firmware bss data section
+ * @custom_psp_footer_size: custom psp footer size to use when indexing for fw meta info
+ */
+struct dmub_srv_fw_meta_info_params {
+ uint32_t inst_const_size;
+ uint32_t bss_data_size;
+ const uint8_t *fw_inst_const;
+ const uint8_t *fw_bss_data;
+ uint32_t custom_psp_footer_size;
};
/**
uint32_t gart_size;
uint8_t num_regions;
struct dmub_region regions[DMUB_WINDOW_TOTAL];
+ uint32_t verified_psp_footer_size;
};
/**
*/
bool dmub_srv_get_preos_info(struct dmub_srv *dmub);
+/**
+ * dmub_srv_get_fw_meta_info_from_raw_fw() - Fetch firmware metadata info from raw firmware image
+ * @params: parameters for fetching firmware metadata info
+ * @fw_info_out: output buffer for firmware metadata info
+ *
+ * Return:
+ * DMUB_STATUS_OK - success
+ * DMUB_STATUS_INVALID - no FW meta info found
+ */
+enum dmub_status dmub_srv_get_fw_meta_info_from_raw_fw(struct dmub_srv_fw_meta_info_params *params,
+ struct dmub_fw_meta_info *fw_info_out);
+
#endif /* _DMUB_SRV_H_ */
}
static const struct dmub_fw_meta_info *
-dmub_get_fw_meta_info(const struct dmub_srv_region_params *params)
+dmub_get_fw_meta_info(const struct dmub_srv_fw_meta_info_params *params)
{
const struct dmub_fw_meta_info *info = NULL;
return info;
}
+enum dmub_status
+dmub_srv_get_fw_meta_info_from_raw_fw(struct dmub_srv_fw_meta_info_params *params,
+ struct dmub_fw_meta_info *fw_info_out)
+{
+ const struct dmub_fw_meta_info *fw_info = NULL;
+ uint32_t inst_const_size_temp = params->inst_const_size;
+
+ /* First try custom psp footer size, if present */
+ if (params->custom_psp_footer_size) {
+ params->inst_const_size -= params->custom_psp_footer_size;
+ fw_info = dmub_get_fw_meta_info(params);
+ if (fw_info) {
+ memcpy(fw_info_out, fw_info, sizeof(*fw_info));
+ return DMUB_STATUS_OK;
+ }
+ params->inst_const_size = inst_const_size_temp;
+ }
+
+ /* Try 256-byte psp footer size */
+ params->inst_const_size -= PSP_FOOTER_BYTES_256;
+ fw_info = dmub_get_fw_meta_info(params);
+ if (fw_info) {
+ memcpy(fw_info_out, fw_info, sizeof(*fw_info));
+ return DMUB_STATUS_OK;
+ }
+
+ /* Try 512-byte psp footer size - final attempt */
+ params->inst_const_size -= PSP_FOOTER_BYTES_256; // 256 bytes already subtracted, subtract 256 again
+ fw_info = dmub_get_fw_meta_info(params);
+ if (fw_info) {
+ memcpy(fw_info_out, fw_info, sizeof(*fw_info));
+ return DMUB_STATUS_OK;
+ }
+
+ /* Restore original inst_const_size and subtract default PSP footer size - default behaviour */
+ params->inst_const_size = inst_const_size_temp - PSP_FOOTER_BYTES_256;
+
+ return DMUB_STATUS_INVALID;
+}
+
static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic)
{
struct dmub_srv_hw_funcs *funcs = &dmub->hw_funcs;
const struct dmub_srv_region_params *params,
struct dmub_srv_region_info *out)
{
- const struct dmub_fw_meta_info *fw_info;
uint32_t fw_state_size = DMUB_FW_STATE_SIZE;
uint32_t trace_buffer_size = DMUB_TRACE_BUFFER_SIZE;
uint32_t shared_state_size = DMUB_FW_HEADER_SHARED_STATE_SIZE;
out->num_regions = DMUB_NUM_WINDOWS;
- fw_info = dmub_get_fw_meta_info(params);
-
- if (fw_info) {
- memcpy(&dmub->meta_info, fw_info, sizeof(*fw_info));
+ if (params->fw_info) {
+ memcpy(&dmub->meta_info, params->fw_info, sizeof(*params->fw_info));
- fw_state_size = fw_info->fw_region_size;
- trace_buffer_size = fw_info->trace_buffer_size;
- shared_state_size = fw_info->shared_state_size;
+ fw_state_size = params->fw_info->fw_region_size;
+ trace_buffer_size = params->fw_info->trace_buffer_size;
+ shared_state_size = params->fw_info->shared_state_size;
/**
* If DM didn't fill in a version, then fill it in based on
* pass during creation.
*/
if (dmub->fw_version == 0)
- dmub->fw_version = fw_info->fw_version;
+ dmub->fw_version = params->fw_info->fw_version;
}
window_sizes[DMUB_WINDOW_0_INST_CONST] = params->inst_const_size;