DF-4319 / df4319.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | /* * DF-4319 — dce80_link_encoder_create unvalidated const-table indexing * --------------------------------------------------------------------- * Host-side reachability proof (no AMD GPU required). * * Exact model of sys/dev/drm/amd/display/dc/dce80/dce80_resource.c:661-678: * * dce110_link_encoder_construct(enc110, enc_init_data, * &link_enc_feature, * &link_enc_regs[enc_init_data->transmitter], * &link_enc_aux_regs[enc_init_data->channel - 1], * &link_enc_hpd_regs[enc_init_data->hpd_source]); * * Table sizes in dce80_resource.c: * link_enc_regs[] : 7 entries (dce80_resource.c:249-257, link_regs(0..6)) * link_enc_aux_regs[] : 6 entries (dce80_resource.c:221-228, aux_regs(0..5)) * link_enc_hpd_regs[] : 6 entries (dce80_resource.c:235-242, hpd_regs(0..5)) * * Index provenance (values the DC core legitimately produces): * transmitter = translate_encoder_to_transmitter() (dc_link.c:1006-1069) * returns TRANSMITTER_UNKNOWN (-1) for ANY unrecognized encoder id/enum * pair (the default arms), TRANSMITTER_NUTMEG_CRT(6) in range, * TRANSMITTER_TRAVIS_CRT(7) / TRAVIS_LCD(8) / UNIPHY_G(9) OUT of range. * channel = get_ddc_line() (dc_link.c:964-1004) * returns CHANNEL_ID_UNKNOWN(0) when the DDC pin is missing/unknown * (-> index -1), CHANNEL_ID_DDC_VGA(7) (-> index 6) and * CHANNEL_ID_I2C_PAD(8) (-> index 7) for valid enum mappings. * hpd_source = get_hpd_line() (dc_link.c:925-962) * returns HPD_SOURCEID_UNKNOWN(6) when no HPD GPIO exists * (-> index 6 on a 6-entry table). * * All three originate from the VBIOS object tables (GPU ROM) parsed by the * BIOS parser. The stored OOB pointers ARE dereferenced later: * AUX_REG(AUX_CONTROL)/AUX_REG(AUX_DPHY_RX_CONTROL0) * dce_link_encoder.c:494,501 -> dm_read_reg/dm_write_reg * HPD_REG(DC_HPD_CONTROL) * dce_link_encoder.c:1370,1384 -> dm_read_reg/dm_write_reg * producing register accesses at addresses read from adjacent static data. * * Build: cc -O2 -Wall -o df4319 df4319.c * Run: ./df4319 * Success criterion: prints the reachable OOB index set per table. */ #include <stdio.h> /* enum values transcribed from sys/dev/drm/amd/display/include/grph_object_defs.h */ enum transmitter { TRANSMITTER_UNKNOWN_DF = -1, /* (:82) */ TRANSMITTER_UNIPHY_A, /* 0 */ TRANSMITTER_UNIPHY_B, /* 1 */ TRANSMITTER_UNIPHY_C, /* 2 */ TRANSMITTER_UNIPHY_D, /* 3 */ TRANSMITTER_UNIPHY_E, /* 4 */ TRANSMITTER_UNIPHY_F, /* 5 */ TRANSMITTER_NUTMEG_CRT, /* 6 */ TRANSMITTER_TRAVIS_CRT, /* 7 */ TRANSMITTER_TRAVIS_LCD, /* 8 */ TRANSMITTER_UNIPHY_G, /* 9 */ }; enum channel_id { CHANNEL_ID_UNKNOWN_DF = 0, /* (:59) */ CHANNEL_ID_DDC1, /* 1 */ CHANNEL_ID_DDC2, CHANNEL_ID_DDC3, CHANNEL_ID_DDC4, CHANNEL_ID_DDC5, CHANNEL_ID_DDC6, /* 6 */ CHANNEL_ID_DDC_VGA, /* 7 */ CHANNEL_ID_I2C_PAD, /* 8 */ }; enum hpd_source_id { HPD_SOURCEID1_DF = 0, /* (:46) */ HPD_SOURCEID2_DF, HPD_SOURCEID3_DF, HPD_SOURCEID4_DF, HPD_SOURCEID5_DF, HPD_SOURCEID6_DF, /* 5 */ HPD_SOURCEID_COUNT_DF = 6, HPD_SOURCEID_UNKNOWN_DF = 6, /* (:54) — alias of COUNT */ }; #define LINK_ENC_REGS_N 7 /* dce80_resource.c:249-257 */ #define LINK_ENC_AUX_REGS_N 6 /* dce80_resource.c:221-228 */ #define LINK_ENC_HPD_REGS_N 6 /* dce80_resource.c:235-242 */ static void check(const char *table, int idx, int n) { printf(" %-34s index %3d vs %d entries : %s\n", table, idx, n, (idx < 0 || idx >= n) ? "*** OUT OF BOUNDS ***" : "ok"); } int main(void) { int tx[] = { TRANSMITTER_UNKNOWN_DF, TRANSMITTER_UNIPHY_A, TRANSMITTER_UNIPHY_F, TRANSMITTER_NUTMEG_CRT, TRANSMITTER_TRAVIS_CRT, TRANSMITTER_TRAVIS_LCD, TRANSMITTER_UNIPHY_G }; int ch[] = { CHANNEL_ID_UNKNOWN_DF, CHANNEL_ID_DDC1, CHANNEL_ID_DDC6, CHANNEL_ID_DDC_VGA, CHANNEL_ID_I2C_PAD }; int hpd[] = { HPD_SOURCEID1_DF, HPD_SOURCEID6_DF, HPD_SOURCEID_UNKNOWN_DF }; unsigned i; puts("dce80_link_encoder_create index reachability " "(values DC core produces for VBIOS objects):"); puts("\n[1] &link_enc_regs[transmitter]:"); for (i = 0; i < sizeof(tx)/sizeof(tx[0]); i++) check("link_enc_regs[transmitter]", tx[i], LINK_ENC_REGS_N); puts("\n[2] &link_enc_aux_regs[channel - 1]:"); for (i = 0; i < sizeof(ch)/sizeof(ch[0]); i++) check("link_enc_aux_regs[channel-1]", ch[i] - 1, LINK_ENC_AUX_REGS_N); puts("\n[3] &link_enc_hpd_regs[hpd_source]:"); for (i = 0; i < sizeof(hpd)/sizeof(hpd[0]); i++) check("link_enc_hpd_regs[hpd_source]", hpd[i], LINK_ENC_HPD_REGS_N); puts("\nDereference sites of the stored OOB pointers:"); puts(" dce_link_encoder.c:494 AUX_REG(AUX_CONTROL) -> dm_read_reg/dm_write_reg"); puts(" dce_link_encoder.c:501 AUX_REG(AUX_DPHY_RX_CONTROL0) -> dm_read_reg/dm_write_reg"); puts(" dce_link_encoder.c:1370 HPD_REG(DC_HPD_CONTROL) -> dm_read_reg/dm_write_reg"); puts(" dce_link_encoder.c:1384 HPD_REG(DC_HPD_CONTROL) -> dm_read_reg/dm_write_reg"); return 0; } |