⬢ DragonFlyBSD Kernel Audit
DF-4047 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/drm/amd/display/dc/bios/command_table.c
+++ b/sys/dev/drm/amd/display/dc/bios/command_table.c
@@ -364,8 +364,13 @@ static enum bp_result transmitter_control_v1_6(
 static void init_transmitter_control(struct bios_parser *bp)
 {
-	uint8_t frev;
-	uint8_t crev;
+	uint8_t frev = 0;
+	uint8_t crev = 0;
 
 	if (BIOS_CMD_TABLE_REVISION(UNIPHYTransmitterControl,
 			frev, crev) == false)
 		BREAK_TO_DEBUGGER();
+
+	/*
+	 * amdgpu_atom_parse_cmd_header() does not write frev/crev when the
+	 * command is absent (atom.c:1412-1413); never switch on uninit
+	 * stack, and never select a handler whose helper entry is NULL
+	 * in the DCE110/DCE112 command_table_helper tables (DF-4047).
+	 */
 	switch (crev) {
 	case 2:
+		if (bp->cmd_helper->transmitter_bp_to_atom == NULL)
+			break;
 		bp->cmd_tbl.transmitter_control = transmitter_control_v2;
 		break;
@@ -369,6 +374,8 @@ static void init_transmitter_control(struct bios_parser *bp)
 	case 4:
+		if (bp->cmd_helper->clock_source_id_to_ref_clk_src == NULL)
+			break;
 		bp->cmd_tbl.transmitter_control = transmitter_control_v4;
 		break;
@@ -160,12 +167,16 @@ static void init_encoder_control_dig_v1(struct bios_parser *bp)
 {
 	struct cmd_tbl *cmd_tbl = &bp->cmd_tbl;
 
-	if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG1EncoderControl))
+	if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG1EncoderControl) &&
+	    bp->cmd_helper->assign_control_parameter != NULL)
 		cmd_tbl->encoder_control_dig1 = encoder_control_dig1_v1;
 	else
 		cmd_tbl->encoder_control_dig1 = NULL;
 
-	if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG2EncoderControl))
+	if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG2EncoderControl) &&
+	    bp->cmd_helper->assign_control_parameter != NULL)
 		cmd_tbl->encoder_control_dig2 = encoder_control_dig2_v1;
 	else
 		cmd_tbl->encoder_control_dig2 = NULL;